【发布时间】:2017-12-27 13:22:27
【问题描述】:
考虑三个域:A、B 和 C。域 A 上的一段 JavaScript 代码对域 B 进行标准 同步 XMLHttpRequest GET 调用,只有一个 Accept 标头,除了默认的。然后域 B 重定向到域 C。两个响应(B 和 C)都将 Access-Control-Allow-Origin 设置为 *。这在 Firefox 中运行良好,正如我所听说的,在 Internet Explorer 中也是如此。但是,Chrome 似乎不允许这样做。然而,异步代码在 Chrome 中也可以工作。
直接向域 C(以及具有相同属性的假设域 D)的同步和异步请求都可以工作。
实际上对 AFAICT 没有帮助的相关事情
我在上面解释了一些简单的事情,以使欺骗锤子使用者更容易阅读:
-
"No 'Access-Control-Allow-Origin' header is present on the requested resource"
是的。 -
只是 Chrome 不允许同步 CORS 请求。
显然,允许非重定向的。 -
DOMException: Failed to execute 'send' on 'XMLHttpRequest' on Chrome only
事实上,这向我指出了它在其他浏览器中确实可以工作的事实,但是说 Firefox 和 IE“不遵循 jQuery 规范”并没有真正的帮助。最重要的是,我的问题不是专门针对 jQuery。另请参阅上述说明:直接请求确实有效。
其他:
-
请求需要预检,但由于其他原因而失败。
我的请求是simple,所以它不应该触发 CORS 预检。方法:GET;标头:Accept;没有指定编辑:对于简单的请求,Content-Type needs to be specified,似乎。我相应地修复了代码示例。Content-Type -
代码无论如何都会触发 CORS 预检,因为 the
Acceptvalue is non-standard
目前不适用于 Chrome。 -
Chrome 让使用同步变得更加困难。
XHRs,据记录在 here。
不,这只是限制了我不使用的另一个功能。 - 我既不控制域 B 也不控制域 C
- 需要从域 B 到 C 的重定向
要测试的代码
以下代码发出一系列请求,首先同步到域 B(重定向到 C),然后异步,然后直接同步到域 C 和异步到 C,并记录结果。请注意,日志可能不会按该顺序排列,因为这基本上是异步的重点。另请注意,在这种情况下,域 B 没有具有Access-Control-Allow-Origin: *,但我已经在域 B 上测试了此代码(本地主机,因此此处不可用)。
function request(url, callback) {
var synchronous = typeof callback !== 'function'
var xhr = new XMLHttpRequest()
if (!synchronous) {
xhr.onload = callback
}
xhr.open('GET', url, !synchronous)
xhr.setRequestHeader('Accept', 'application/vnd.citationstyles.csl+json')
xhr.setRequestHeader('Content-Type', 'text/plain')
xhr.send(null)
return xhr
}
var previewLength = 100
function handle(passed, message, data) {
var item = document.createElement('li')
item.innerText = message + (passed ? ' passed: ' : ' failed: ') + data
var list = passed ? p : f
list.appendChild(item)
}
var doi = '10.1093/BIOINFORMATICS/BTT178'
var domainB = 'doi.org'
var domainC = 'data.crossref.org'
var urlRedirect = '//' + domainB + '/' + doi
var urlDirect = '//' + domainC + '/' + doi
// sync domain B->C request
try {
var response = request(urlRedirect)
handle(true, 'sync domain B->C', response.responseText.slice(0, previewLength) + '...')
} catch (e) {
handle(false, 'sync domain B->C', e)
}
// async domain B->C request
request(urlRedirect, function() {
if (this.responseText[0] === '{') {
handle(true, 'async domain B->C', this.responseText.slice(0, previewLength) + '...')
} else {
handle(false, 'async domain B->C')
}
})
// sync domain C request
try {
var response = request(urlDirect)
handle(true, 'sync domain C', response.responseText.slice(0, previewLength) + '...')
} catch (e) {
handle(false, 'sync domain C', e)
}
// async domain C request
request(urlDirect, function() {
if (this.responseText[0] === '{') {
handle(true, 'async domain C', this.responseText.slice(0, previewLength) + '...')
} else {
handle(false, 'async domain C')
}
})
Passed:
<ul id=p></ul>Failed:
<ul id=f></ul>
我的问题
- 是否有任何文档说明 Chrome 为何以及何时这样做?
- 是否有解决方法(即同步重定向 CORS 请求)?我知道您无法阻止
XMLHttpRequest中的重定向,但也许还有其他方法。
我正在运行 Chromium 57.0.2987.98 32 位。
【问题讨论】:
-
我认为只是同步调用最近已被弃用并从 Chrome 中删除。
标签: javascript google-chrome xmlhttprequest cors synchronous