ModifyAjaxResponse,修改ajax请求返回值,前后端调试之利器
一、概要
先看图
京豆多的离谱,你的第一想法肯定是:按F12修改了网页元素
没那么简单,你看支持刷新的
肯定还是假的,通过 Fiddler 或 Wireshark 等抓包工具修改了响应包;或者干脆改了本地host文件,指向了一个自己写的页面......
这些都太麻烦了,如果能在当前网页上拦截这个请求,并修改返回值,那才是最简单的
二、尝试
一个简单的ajax请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>test</title> </head> <body> <div> <input type="button" value="get_data" id="xhr_get"> </div> <div> <p>id -> <span id="id"></span></p> <p>title -> <span id="title"></span></p> <p>userId -> <span id="userId"></span></p> <p>body -> <span id="body"></span></p> </div> <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script> <script type="text/javascript"> $('#xhr_get').on('click', function () { $.ajax({ url: 'https://jsonplaceholder.typicode.com/posts/1', type: 'GET', success: function (data) { $('#id').text(data.id); $('#title').text(data.title); $('#userId').text(data.userId); $('#body').text(data.body); } }); }); </script> </body> </html>
运行起来,点下按钮看看
如何拦截这个ajax请求并修改返回内容呢?
可以实现一个自定义的构造函数重写默认的XMLHttpRequest构造函数,使其在触发实际事件之前重写响应即可。按F12在控制台向页面注入代码试试(也可以写到 html页面里,效果一样)
var ajax_open_original = XMLHttpRequest.prototype.open; function intercept_ajax(rule) { XMLHttpRequest.prototype.open = function () { var open_arguments = arguments; var url = open_arguments[1]; var flag = false; var xhrTxt = ''; if (url.indexOf(rule.pattern) > -1) { flag = true; xhrTxt = rule.response; } this.addEventListener('readystatechange', function (event) { if (flag && this.readyState === 4) { Object.defineProperty(this, 'response', { writable: true }); Object.defineProperty(this, 'responseText', { writable: true }); this.response = this.responseText = xhrTxt; } }); return ajax_open_original.apply(this, open_arguments); }; }; intercept_ajax({ pattern: 'https://jsonplaceholder.typicode.com/posts/1', response: JSON.stringify({ id: 1, title: '2', userId: 3, body: 'body' }) });
再次点击按钮,页面已经渲染到新的值了
由此证明,这条路是行的通的,但是不能每次都按F12注入,应该做到自动注入,并把所有拦截规则维护起来
三、Chrome插件
浏览器插件最适合做这个了,新建一个Chrome插件,命名:ModifyAjaxResponse
manifest.json
{ "manifest_version": 3, "name": "ModifyAjaxResponse", "description": "Modify response text of ajax requests", "version": "1.4.0", "content_scripts": [ { "matches": [ "<all_urls>" ], "js": [ "content_scripts.js" ], "run_at": "document_start" } ] }
"run_at": "document_start",页面加载之前就注入 content_scripts.js,看看其内容
const script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('src', chrome.runtime.getURL('dist/pageInjectScript.js')); document.documentElement.appendChild(script);
向页面动态加载 pageInjectScript.js,用来重写默认的 XMLHttpRequest 构造函数,实现拦截ajax请求。打开博客园测试一下
可见 pageInjectScript.js 已经加载进来了,这个不是博客园服务器返回的,而是通过Chrome插件注入的。既然已经注入页面了,那当前页面所有的ajax请求都可以被重写
还差一个维护所有拦截规则的页面。使用 Chrome API 自带的存储 chrome.storage.local 保存即可。简单画个页面,看看最终效果
至此,已经可以指哪打哪,随意修改页面展示内容了
四、总结
这个当然不是改京豆数量自嗨用的,实际用途以及开发初衷是:前后端对接接口,前端利用本插件,可以快速得到不同的返回值
注:
1)本插件仅重写XMLHttpRequest构造函数,F12网络面板里看到的还是原始返回值,但代码可以获取修改后的值;
2)非开发时间请关闭插件,避免向页面注入无用js
五、相关阅读
六、下载
源码:https://github.com/oppoic/ModifyAjaxResponse
Chrome 商店:https://chrome.google.com/webstore/detail/modifyajaxresponse/odpiadnfijfeggnnodoaaphkkjkmpnia
注:访问不了 Chrome 商店的话,下载源码本地加载src目录