在用户脚本中运行 XMLHttpRequest 时,“无法添加 CORS 标头‘Origin’”

问题描述

我有一个使用 FireMonkey 运行的用户脚本,它在特定站点上向我的主服务器发出请求以检索一些数据。到目前为止,我一直在使用 jQuery AJAX,只要我在服务器端设置了一些标头来处理 CORS,它就可以正常工作:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Method: POST");
header("Access-Control-Allow-Headers: Content-Type,Origin");

我现在想做的是摆脱 jQuery,因为在此之前 AJAX 请求是我真正使用它的唯一内容,而是尝试以经典的 XMLHttpRequest 方式实现请求。不幸的是,由于某种原因,使用 XHR 会以readyState === 4status === 0失败。

在 Firefox 上使用浏览器内容工具箱时,我发现了一个隐藏的 CORS 阻塞错误,原因是 CORS header 'Origin' cannot be added,我几乎找不到除 Access-Control-Allow-Origin 之外的任何其他信息可能会丢失。在本地测试脚本,XHR 的请求标头与 AJAX 的请求标头没有任何区别(X-Requested-With: XMLHttpRequest 除外,我为 XHR 手动设置)。请求失败的原因可能是什么? AJAX 是否在做我遗漏的事情?

我没有将 GM_XMLHttpRequest 用于用户脚本,因为我已经为请求实现了自己的样板,我也将这些样板捆绑到我的相关本地脚本中。不过,我已经阅读了一些关于使用不同请求库的意见,例如 superagent,我不太确定它们是否可以更正确地使用用户脚本同时也是轻量级的。我很乐意为替代方案提供任何建议。

我使用 Mozilla Firefox 和 FireMonkey 来托管用户脚本。

提前致谢!

解决方法

jQuery AJAX 只是一个基于 XMLHttpRequest 的函数。

带有任何用户脚本管理器的用户脚本,在本例中为 FireMonkey,可以根据 上下文 发出 3 种类型的 XHR 请求:

  • fetch & XMLHttpRequest 来自 page 上下文(注入网页的 JS 代码)
    请求将从页面发送并受页面 CSP 和 CORS 约束
  • fetch & XMLHttpRequest 来自 userScript 上下文(FireMonkey)或 content 上下文(其他管理器)
    请求将从用户脚本发送并受 CORS 约束
  • GM.fetch|GM_fetch(仅限 FireMonkey)和 GM.xmlHttpRequest|GM_xmlhttpRequest 来自 browser 上下文
    请求将从后台js发送,不受CORS约束,但不会有凭据

Forbidden header name 列出了不允许在 Firefox(和其他现代浏览器)中修改的标题。

FireMonkey 还会从 GM.fetch|GM_fetchGM.xmlHttpRequest|GM_xmlhttpRequest 中去除 Forbidden 标头,但允许以下例外情况:Cookie、Host、Origin、Referer
(参考:FireMonkey 帮助下“禁止的标题名称”)

总而言之,在用户脚本中更改 Origin 标头的唯一方法是使用 GM fetch|xmlHttpRequest。