如何在回调脚本包装器中捕获响应并覆盖相应的响应头?
幸好,我已经设法使用JavaScript函数从远程源下载元数据:
function scriptWrapper(responseObject) {
// parse jsonp and override DOM object inner html value
}
const doGetMetaDataEvent = async () => {
setInterval(async () => {
const script = document.createElement('script');
script.src = METADATA_SOURCE + '?callback=scriptWrapper';
document.getElementsByTagName('head')[0].appendChild(script);
}, REFRESH_TIMEOUT);
}
但我在浏览器中禁用刷新时遇到了问题:The script from “https://radiohost.example.endpoint&informationjson=true?callback=scriptWrapper” was loaded even though its MIME type (“application/jsonp”) is not a valid JavaScript MIME。
所以需要解决的问题是在何处捕获响应并覆盖其中的响应头:response.setHeader('X-Content-Type-Options', 'nosniff')
解决方案
在浏览器中无法完成这件事。
当你加载一个URL时:
const script = document.createElement('script');
script.src = METADATA_SOURCE + '?callback=scriptWrapper';
document.head.appendChild(script);
浏览器会将该URL视为一个 脚本资源。这意味着远端服务器必须返回实际的JavaScript,例如:
scriptWrapper({ ...data... });
以及类似以下的脚本MIME类型:
Content-Type: application/javascript
在你的场景中,响应返回的是:
Content-Type: application/json
X-Content-Type-Options: nosniff
因此浏览器会正确拒绝将其作为脚本执行。
另外,这一部分:
response.setHeader('X-Content-Type-Options', 'nosniff')
也不是你可以通过客户端JavaScript完成的。响应头是由 发送响应的服务器 设置的,而不是由包含该脚本的页面设置的。
所以只有三种真正的选项:
- 修复远端端点 以返回JSONP
示例响应主体:
scriptWrapper({ ...data... });
与:
Content-Type: application/javascript
2. 使用 fetch() / XHR而不是 <script> 注入
这需要远端服务器允许CORS。
async function doGetMetaDataEvent() {
const res = await fetch(METADATA_SOURCE);
const data = await res.json();
scriptWrapper(data);
}
3. 使用你自己的后端/代理
你的服务器获取远端JSON,然后要么:
- 将其作为JSON返回给前端,或者
- 如果你确实需要回调风格的加载,则将其转换为JSONP。
因此,对你的问题的答案是:在 scriptWrapper 中没有任何地方可以“捕获响应并覆盖头部信息”。在 scriptWrapper 运行时,浏览器已经接受或拒绝了该资源。头信息必须在脚本加载之前就由服务器端正确设置。