重写XMLHttpRequest.send方法修改POST请求体未生效问题求助
问题原因
你代码的核心问题是没有备份原生XMLHttpRequest.prototype.send方法,你调用的this.realSend并未提前定义,替换后的发送逻辑本身存在异常,因此修改不会生效。此外如果站点使用Fetch API发送请求,只修改XHR逻辑也无法覆盖所有请求场景。
修复方案
1. 正确实现XHR请求拦截
// 先备份原生send方法,避免丢失原始逻辑 XMLHttpRequest.prototype.realSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(body) { // 仅对JSON格式的请求体做修改,避免异常 if (body && typeof body === 'string') { try { const newBody = JSON.parse(body); // 仅当请求体存在points字段时修改,避免影响无关请求 if (newBody && typeof newBody === 'object' && Reflect.has(newBody, 'points')) { newBody.points = 417; body = JSON.stringify(newBody); } } catch (err) { // 非JSON格式直接跳过修改,不影响原有请求逻辑 } } // 调用原生发送逻辑传入修改后的请求体 return this.realSend.call(this, body); };
2. 补充Fetch请求拦截(可选,适配使用Fetch的站点)
现在大部分新站点会使用Fetch API而非XHR发送请求,需要补充对应拦截逻辑才能覆盖所有场景:
const originalFetch = window.fetch; window.fetch = function(input, init = {}) { // 仅处理带请求体的POST类请求 if (init.method && init.method.toUpperCase() === 'POST' && init.body) { try { if (typeof init.body === 'string') { const newBody = JSON.parse(init.body); if (newBody && Reflect.has(newBody, 'points')) { newBody.points = 417; init.body = JSON.stringify(newBody); // 更新Content-Length请求头,避免请求体被截断 if (init.headers) { if (init.headers instanceof Headers) { init.headers.set('Content-Length', String(init.body.length)); } else if (Array.isArray(init.headers)) { const clIdx = init.headers.findIndex(([key]) => key.toLowerCase() === 'content-length'); clIdx > -1 ? init.headers[clIdx][1] = String(init.body.length) : init.headers.push(['Content-Length', String(init.body.length)]); } else { init.headers['Content-Length'] = String(init.body.length); } } } } } catch (err) { // 格式不匹配直接跳过 } } return originalFetch.apply(this, arguments); };
注意事项
- 拦截代码必须在页面发送任何请求前执行,如果是控制台手动运行,需要刷新页面后、请求触发前执行代码,若页面已提前缓存了原始的XHR/Fetch方法,后续修改原型也不会生效
- 如果请求体是FormData、URLSearchParams等非JSON格式,需要对应调整解析和修改逻辑
- 部分站点会做请求体签名校验,修改请求体后签名不匹配会导致请求被服务端拒绝,这种情况需要同步调整签名逻辑才能生效
内容的提问来源于stack exchange,提问作者Phenomenon
相关产品推荐
相关产品推荐

