在 OpenResty 中 Hook WebWorker 的 fetch
函数需要通过修改返回的 HTML/JavaScript 代码来实现,因为 OpenResty 本身无法直接干预浏览器中 WebWorker 的运行环境。以下是具体步骤和示例:
1. 方案思路
- 目标:拦截 WebWorker 中的
fetch
请求。 - 限制:OpenResty 只能操作上游返回的 HTML/JS 代码,无法直接修改运行时的 WebWorker 行为。
- 方法:
- 注入脚本:在返回的 HTML 中插入一段 JavaScript,覆盖 WebWorker 的
fetch
方法。 - 劫持通信:通过
postMessage
/onmessage
将 WebWorker 的请求转发到主线程,由主线程统一处理。
- 注入脚本:在返回的 HTML 中插入一段 JavaScript,覆盖 WebWorker 的
2. Lua 代码示例(OpenResty)
以下是一个完整的 OpenResty Lua 脚本,用于修改响应内容并注入 Hook 逻辑:
location /your-upstream-path {
proxy_pass http://your-backend;
header_filter_by_lua_block {
-- 仅处理 HTML 响应
if ngx.header["Content-Type"] and string.find(ngx.header["Content-Type"], "text/html") then
ngx.header["Content-Length"] = nil -- 清除 Content-Length,因为我们会修改 body
end
}
body_filter_by_lua_block {
-- Hook WebWorker.fetch()
local inject_script = [[
<script>
// Hook WebWorker.fetch() by overriding the Worker's importScripts or constructor
(function() {
const originalFetch = window.fetch;
window.fetch = function(...args) {
console.log("Intercepted fetch in main thread:", args);
return originalFetch.apply(this, args);
};
const originalWorker = window.Worker;
window.Worker = function(url, options) {
// Fetch the worker script and modify it to hook fetch()
const workerScript = originalFetch(url)
.then(response => response.text())
.then(text => {
// Inject our hook into the Worker's code
const patchedScript = `
const originalFetchInWorker = fetch;
fetch = function(...args) {
console.log("Intercepted fetch in Worker:", args);
return originalFetchInWorker.apply(this, args);
};
${text}
`;
return new Blob([patchedScript], { type: 'application/javascript' });
})
.then(blob => URL.createObjectURL(blob));
return new originalWorker(workerScript, options);
};
})();
</script>
]]
-- Inject the script before </body>
local body = ngx.arg[1]
if body then
body = string.gsub(body, "</body>", inject_script .. "</body>")
ngx.arg[1] = body
end
}
}
3. Key Points
动态修改 Worker:
- Override
window.Worker
constructor. - Fetch the worker script via
fetch
, modify it to inject our hook, then create a blob URL for the new Worker.
- Override
Hook Logic:
- Override
fetch
in both main thread and worker.
- Override
注意事项:
- Requires CORS support if fetching cross-origin worker scripts.
- May break if the worker uses dynamic imports or other advanced features.
Alternative Approach: If you control the worker script, directly modify its source code to include the hook logic instead of patching it dynamically.
4 Testing
Test with a simple web page that uses a webworker making fetch requests to verify interception works as expected.
Let me know if you need any clarification or have questions about specific parts!
内容由零声教学AI助手提供,问题来源于学员提问