使用子域时防止预检选项
Prevent preflight OPTIONS when using sub domains
给定两个子域:
web.mysite.com
和 api.mysite.com
当前发出从 web.
到 api.
的任何请求都会导致发出预检 OPTIONS 请求。如果它没有为中国的请求增加额外的 600 毫秒,这就不是什么大问题。
有人告诉我在 JS 中设置 document.domain = 'mysite.com';
可以解决问题,但这根本没有帮助。
是否可以/如何在发送到不同的子域时禁用 OPTIONS 请求。
使用 iframe
技术解决了这个问题,这似乎是 Facebook / Twitter 所做的。
以下步骤:
1) 设置document.domain
为根域。所以给定 url http://site.mysite.com/
我在 JavaScript 中设置域,例如 document.domain = 'mysite.com';
2) 设置一个从 API 域中提取 HTML 文件的 iframe。
<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
事件以在加载后捕获 window。
onload="window.tempIframeCallback()"
5) 将 child window 分配给一个变量。
window.tempIframeCallback = function() {
window.childWindow = window.receiver.contentWindow;
}
6) 从 childWindow 而不是主要的 window 创建 XMLHttpRequest()
。
var xhr = new window.childWindow.XMLHttpRequest();
现在所有请求都将在没有预检 OPTIONS
请求的情况下发送。
7)使用jQuery时,也可以在settings中设置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 代码中,您现在可以像使用 fetch
和 XMLHttpRequest
一样使用 APIfetch
和 APIXMLHttpRequest
... 等等,无论使用何种方法和内容类型,都不再需要预检请求!
这是一个完整的 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);
其中 API_URL + '/iframe' returns 这个:
<!DOCTYPE html><body><script>document.domain = 'mysite.net'</script></body></html>
给定两个子域:
web.mysite.com
和 api.mysite.com
当前发出从 web.
到 api.
的任何请求都会导致发出预检 OPTIONS 请求。如果它没有为中国的请求增加额外的 600 毫秒,这就不是什么大问题。
有人告诉我在 JS 中设置 document.domain = 'mysite.com';
可以解决问题,但这根本没有帮助。
是否可以/如何在发送到不同的子域时禁用 OPTIONS 请求。
使用 iframe
技术解决了这个问题,这似乎是 Facebook / Twitter 所做的。
以下步骤:
1) 设置document.domain
为根域。所以给定 url http://site.mysite.com/
我在 JavaScript 中设置域,例如 document.domain = 'mysite.com';
2) 设置一个从 API 域中提取 HTML 文件的 iframe。
<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
事件以在加载后捕获 window。
onload="window.tempIframeCallback()"
5) 将 child window 分配给一个变量。
window.tempIframeCallback = function() {
window.childWindow = window.receiver.contentWindow;
}
6) 从 childWindow 而不是主要的 window 创建 XMLHttpRequest()
。
var xhr = new window.childWindow.XMLHttpRequest();
现在所有请求都将在没有预检 OPTIONS
请求的情况下发送。
7)使用jQuery时,也可以在settings中设置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 代码中,您现在可以像使用 fetch
和 XMLHttpRequest
一样使用 APIfetch
和 APIXMLHttpRequest
... 等等,无论使用何种方法和内容类型,都不再需要预检请求!
这是一个完整的 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);
其中 API_URL + '/iframe' returns 这个:
<!DOCTYPE html><body><script>document.domain = 'mysite.net'</script></body></html>