如何拦截所有http请求,包括表单提交
Posted
技术标签:
【中文标题】如何拦截所有http请求,包括表单提交【英文标题】:How to intercept all http requests including form submits 【发布时间】:2017-10-04 10:57:15 【问题描述】:我想拦截从我的网页发出的所有 http 请求,并在请求正文中添加一个参数。我的页面包含表单 - 我还想捕获表单提交。我曾尝试使用 Jquery ajaxSend 和 javascript 的 setRequestHeader,但两者都不适合我。我如何做到这一点?
谢谢
【问题讨论】:
我不认为 Javascript 可以拦截常规的表单提交。您可以捕获提交事件,然后改为使用 AJAX 发送表单。 您可以捕获表单提交并将输入插入到表单中。就 ajax 请求而言,如果您只使用 jquery,全局 ajax 事件就可以工作。没有一种解决方案可以解决问题。 在我的例子中,页面是使用 Apache 速度视图模板生成的——这意味着每个页面都是通过将页面模板与标题模板组合生成的。有很多页面,我希望所有页面都能够向服务器发送令牌。似乎实现这一点的唯一方法似乎是在标头中添加代码以拦截请求。所以建议的解决方案不起作用。有没有其他办法? 也许吧。 Jquery 中的类选择器可能对我有用!谢谢! @lenniekid 您想在请求正文或请求标头中添加参数吗?如果是正文,您可以按照上面的建议添加一个隐藏的表单字段。 【参考方案1】:https://developer.mozilla.org/en/docs/Web/API/Service_Worker_API
Service Worker 本质上充当位于 Web 应用程序、浏览器和网络(如果可用)之间的代理服务器。
它采用JavaScript文件的形式,可以控制与之关联的网页/站点,拦截和修改导航和资源请求
您通过以下方式在您的应用程序代码中注册一个服务工作者,例如,sw.js
:
if ('serviceWorker' in navigator)
window.addEventListener('load', function()
navigator.serviceWorker.register('sw.js').then(function(registration)
console.log('Service worker registered with scope: ', registration.scope);
, function(err)
console.log('ServiceWorker registration failed: ', err);
);
);
在sw.js
文件中(实际的 service-worker 代码):要拦截请求,您将 fetch
事件侦听器附加到调用 respondWith()
方法并使用 .request
执行某些操作的 service worker来自事件对象的成员:
self.addEventListener('fetch', function(event)
event.respondWith(
// intercept requests by handling event.request here
);
);
一个简单的服务工作者,只是通过请求不变看起来像这样:
self.addEventListener('fetch', function(event)
event.respondWith(
fetch(event.request)
);
);
要将参数添加到请求正文中,您需要:
-
序列化请求。
修改该序列化请求。
反序列化修改后的请求以创建新请求。
致电
fetch(…)
提出新请求。
所以,一个服务工作者会做所有看起来像这样的事情(未经测试):
self.addEventListener('fetch', function(event)
event.respondWith(
fetchWithParamAddedToRequestBody(event.request)
);
);
function fetchWithParamAddedToRequestBody(request)
serialize(request).then(function(serialized)
// modify serialized.body here to add your request parameter
deserialize(serialized).then(function(request)
return fetch(request);
);
); // fixed this
function serialize(request)
var headers = ;
for (var entry of request.headers.entries())
headers[entry[0]] = entry[1];
var serialized =
url: request.url,
headers: headers,
method: request.method,
mode: request.mode,
credentials: request.credentials,
cache: request.cache,
redirect: request.redirect,
referrer: request.referrer
;
if (request.method !== 'GET' && request.method !== 'HEAD')
return request.clone().text().then(function(body)
serialized.body = body;
return Promise.resolve(serialized);
);
return Promise.resolve(serialized);
function deserialize(data)
return Promise.resolve(new Request(data.url, data));
注意:https://serviceworke.rs/request-deferrer_service-worker_doc.html,来自Service Worker Cookbook 的页面,是我从serialize(…)
代码/方法中提取的地方——通过https://***.com/questions/35420980/how-to-alter-the-headers-of-a-request/35421644#35421644—and 的答案,值得一试看一下,因为那里的代码有详细的注释解释它在做什么
【讨论】:
这太酷了,我有我需要的东西来解决我的问题。下一秒我检查了this 和最亲爱的 - IE 和 Edge :) 上帝保佑他们 Service Worker 是 Web Worker 的别称还是不同? 在带有 iframe 的页面中触发时是否跟踪 api 调用?如果调用到其他域(sso)并返回到同一个域(它是否也拦截了那个 api?)【参考方案2】:试试这个代码:
(function(send)
XMLHttpRequest.prototype.send = function(data)
var _valuToAdd = $("input[name='valuToAdd']").val();
this.setRequestHeader('valueName', _valuToAdd);
send.call(this, data);
;
)(XMLHttpRequest.prototype.send);
【讨论】:
不拦截表单提交。 这不是拦截简单的获取请求。以上是关于如何拦截所有http请求,包括表单提交的主要内容,如果未能解决你的问题,请参考以下文章