在使用子域时防止预飞行选项

Prevent preflight OPTIONS when using sub domains

本文关键字:飞行 选项      更新时间:2023-09-26

给定两个子域:

web.mysite.comapi.mysite.com

当前从web.api.的任何请求都会导致飞行前选项请求。如果它没有在中国额外增加600ms的请求时间,这就不是什么大问题了。

有人告诉我,在JS中设置document.domain = 'mysite.com';可以解决这个问题,但这根本没有帮助。

是可能的/我怎么能禁用OPTIONS请求时发送到只是一个不同的子域

使用iframe技术解决了这个问题,这似乎是Facebook/Twitter所做的。

下面的步骤:

1)设置document.domain为根域。url为http://site.mysite.com/,域名设置为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>

4)在iframe中添加了一个onload事件,以便在加载后捕获窗口。

onload="window.tempIframeCallback()"

5)将子窗口赋值给变量

window.tempIframeCallback = function() {
  window.childWindow = window.receiver.contentWindow;
}

6)使XMLHttpRequest()从childWindow而不是主窗口。

var xhr = new window.childWindow.XMLHttpRequest();

现在所有的请求将发送没有飞行前OPTIONS请求。


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

$.ajax({
  ...
  xhr: function() {
    return new window.childWindow.XMLHttpRequest();
  }
});

作为@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>

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

<!DOCTYPE html>
<html><body><script>
    document.domain='mysite.com';
</script></body></html>

然后,在你的JS代码中,你现在可以像使用fetchXMLHttpRequest一样使用APIfetchAPIXMLHttpRequest…因此,无论使用什么方法和内容类型,都不会有更多的预飞行请求!

这是一个全javascript的方法:

document.domain = 'mysite.net';
var apiIframe = document.createElement('iframe');
apiIframe.onload = function(){
    window.XMLHttpRequest = this.contentWindow.XMLHttpRequest;
};
apiIframe.setAttribute('src', API_URL + '/iframe');
apiIframe.style.display = 'none';
document.body.appendChild(apiIframe);

where API_URL + '/iframe'返回这个:

<!DOCTYPE html><body><script>document.domain = 'mysite.net'</script></body></html>