Javascript 使用后台页面的跨域 XMLHttpRequest
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7699615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross-domain XMLHttpRequest using background pages
提问by yuzeh
In my Chrome extension, I want to have my options.html
page communicate with something like Google's OpenId API. In order to do this seamlessly, I have a hidden iframe
on the options page which will pop-up the Google Accounts login page (following the OpenId interaction sequence, etc.).
在我的 Chrome 扩展程序中,我想让我的options.html
页面与 Google 的 OpenId API 之类的东西进行通信。为了无缝地做到这一点,我iframe
在选项页面上有一个隐藏,它将弹出 Google 帐户登录页面(遵循 OpenId 交互序列等)。
My issue is that I can't communicate from the options page to the iframe
(the origin of the iframe
is something I control, but not the same as my chrome extension) via window.postMessage
. I was wondering if there is a quick workaround to this issue.
我的问题是,我无法从选项页传达给iframe
(的起源iframe
经是我控制,但由于我的Chrome扩展不一样的)window.postMessage
。我想知道是否有解决此问题的快速解决方法。
If there isn't, I'm going to make options.html
contain an iframe
that houses the layout and logic of the page.
如果没有,我将创建options.html
一个包含iframe
页面布局和逻辑的内容。
回答by Rob W
You don't have to mess with iframes. It's possible to perform cross-domain XMLHttpRequests, using background pages. Since Chrome 13, cross-site requests can be made from the content script. However, requests can still fail if the page is served with a Content Security Policy header with a restricting connect-src
.
您不必弄乱 iframe。可以使用后台页面执行跨域 XMLHttpRequests。从 Chrome 13 开始,可以从内容脚本发出跨站点请求。但是,如果页面使用带有限制connect-src
.
Another reason for choosing the nexy method over content scripts is that requests to http sites will cause a mixed content warning ("The page at https://... displayed insecure content from http://...").
选择 nexy 方法而不是内容脚本的另一个原因是对 http 站点的请求将导致混合内容警告(“https://... 上的页面显示来自 http://... 的不安全内容”)。
Yet another reason for delegating the request to the background page is when you want to get a resource from the file://
, because a content script cannot read from file:
, unless it is running on a page at the file://
scheme.
将请求委托给后台页面的另一个原因是当您想要从 获取资源时file://
,因为内容脚本无法从 读取file:
,除非它在该file://
方案的页面上运行。
Note
To enable cross-origin requests, you have to explicitly grant permissions to your extension using thepermissions
array in your manifest file.
注意
要启用跨域请求,您必须使用permissions
清单文件中的数组明确授予扩展程序权限。
Cross-site request using background script.
使用后台脚本的跨站点请求。
The content script would request the functionality from the background via the messagingAPI. Here is an example of a very simple way of sending and getting the response of a request.
内容脚本将通过消息传递API从后台请求功能。这是发送和获取请求响应的非常简单的方法的示例。
chrome.runtime.sendMessage({
method: 'POST',
action: 'xhttp',
url: 'http://www.stackoverflow.com/search',
data: 'q=something'
}, function(responseText) {
alert(responseText);
/*Callback function to deal with the response*/
});
Background/ eventpage:
/**
* Possible parameters for request:
* action: "xhttp" for a cross-origin HTTP request
* method: Default "GET"
* url : required, but not validated
* data : data to send in a POST request
*
* The callback function is called upon completion of the request */
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
if (request.action == "xhttp") {
var xhttp = new XMLHttpRequest();
var method = request.method ? request.method.toUpperCase() : 'GET';
xhttp.onload = function() {
callback(xhttp.responseText);
};
xhttp.onerror = function() {
// Do whatever you want on error. Don't forget to invoke the
// callback to clean up the communication port.
callback();
};
xhttp.open(method, request.url, true);
if (method == 'POST') {
xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
xhttp.send(request.data);
return true; // prevents the callback from being called too early on return
}
});
Remark: The messaging APIs have been renamed several times. If your target browser is not the latest Chrome version, check out this answer.
备注:消息 API 已多次重命名。如果您的目标浏览器不是最新的 Chrome 版本,请查看此答案。
For completeness, here's a manifestfile to try out my demo:
为了完整起见,这里有一个清单文件来试用我的演示:
{
"name": "X-domain test",
"manifest_version": 2,
"permissions": [
"http://www.stackoverflow.com/search*"
],
"content_scripts": {
"js": ["contentscript.js"],
"matches": ["http://www.example.com/*"]
},
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
回答by kishoreballa
I implemented the same thing using jquery its much simpler and it worked great too..
我使用 jquery 实现了同样的事情,它更简单,而且效果很好。
background.js
背景.js
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
if (request.action == "xhttp") {
$.ajax({
type: request.method,
url: request.url,
data: request.data,
success: function(responseText){
callback(responseText);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
//if required, do some error handling
callback();
}
});
return true; // prevents the callback from being called too early on return
}
});
contentscript.js
内容脚本.js
chrome.runtime.sendMessage({
method: 'POST',
action: 'xhttp',
url: 'http://example-url.com/page.php',
data: "key=value"
}, function(reponseText) {
alert(responseText);
});
But make sure manifest.json file has required permissions and jquery js file
但请确保 manifest.json 文件具有所需的权限和 jquery js 文件
"permissions": [
"tabs", "activeTab", "http://example-url.com/*"
],
"content_scripts": [ {
"js": [ "jquery-3.1.0.min.js", "contentscript.js" ],
"matches": [ "https://example-ssl-site.com/*" ]
}],
"background": {
"scripts": [ "jquery-3.1.0.min.js", "background.js" ]
}