使用子域时防止预检OPTIONS

Phi*_*ill 12 javascript ajax cors

给出两个子域:

web.mysite.comapi.mysite.com

目前正在进行任何请求,web.api.产生预检OPTIONS请求.如果它没有在中国增加额外600毫秒的请求,这不会是一个问题.

我被告知document.domain = 'mysite.com';JS 中的设置可以解决问题,但这根本没有帮助.

是否可以/如何在发送到不同的子域时禁用OPTIONS请求.

Phi*_*ill 10

使用iframe似乎是Facebook/Twitter 的技术解决了这个问题.

步骤如下:

1)将其设置document.domain为根域.所以给定url http://site.mysite.com/我在JavaScript中设置域名就像document.domain = 'mysite.com';

2)设置iframe,从API域中提取HTML文件.

<iframe id="receiver" src="http://api.mysite.com/receiver" style="position:absolute;left:-9999px"></iframe>

这被设置为无法看到.

3)设置接收者页面的HTML以设置域:

<!DOCTYPE html><body><script>document.domain='mysite.com'</script></body></html>
Run Code Online (Sandbox Code Playgroud)

4)onload向iframe 添加一个事件,以便在加载窗口后捕获它.

onload="window.tempIframeCallback()"
Run Code Online (Sandbox Code Playgroud)

5)将子窗口分配给变量.

window.tempIframeCallback = function() {
  window.childWindow = window.receiver.contentWindow;
}
Run Code Online (Sandbox Code Playgroud)

6)充分利用XMLHttpRequest()从childWindow而不是主窗口.

var xhr = new window.childWindow.XMLHttpRequest();
Run Code Online (Sandbox Code Playgroud)

现在,所有请求都将在没有预检OPTIONS请求的情况下发送.


7)使用jQuery时,您还可以在设置中设置xhr的来源:

$.ajax({
  ...
  xhr: function() {
    return new window.childWindow.XMLHttpRequest();
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢你的想法!对于未来的读者,这也适用于`fetch` API,使用`window.childWindow.fetch()`而不是`window.fetch()`.疯狂,网络标准不能适应这样的情况,没有像这样的黑客解决方案...... (3认同)

ouk*_*ouk 6

作为对@Phill 的回答的补充,值得所有学分,这是最终的 html 代码,它也公开了 iframe 的fetch功能:

<!DOCTYPE html>
<html><body>
<script>
    document.domain = 'mysite.com';
    window.setupAPI = function() {
        var receiverWindow = window.receiver.contentWindow;
        // you may also want to replace window.fetch here
        window.APIfetch = receiverWindow.fetch;
        // same thing, you may as well replace window.XMLHttpRequest
        window.APIXMLHttpRequest = receiverWindow.XMLHttpRequest;
    }
</script>
<iframe id="receiver" 
        src="http://api.mysite.com/receiver" 
        style="position:absolute;left:-9999px"
        onload="window.setupAPI()"></iframe>
</body></html>
Run Code Online (Sandbox Code Playgroud)

当然,HTML“ http://api.mysite.com/receiver ”应该检索:

<!DOCTYPE html>
<html><body><script>
    document.domain='mysite.com';
</script></body></html>
Run Code Online (Sandbox Code Playgroud)

然后,你的JS代码中,你现在可以使用APIfetchAPIXMLHttpRequest你一样会使用fetchXMLHttpRequest...等瞧,无论使用任何更多的预检请求的方法和内容类型!