书签中的XmlHttpRequest在GET上返回空的responseText? [英] XmlHttpRequest in a bookmarklet returns empty responseText on GET?
问题描述
我正在尝试为我们在 http://esv.to上构建的特殊网址缩短服务构建一个javascript书签缩短经文参考(即马修5成为 http://esv.to/Mt5。小书签应该对 http://api.esv.to/Matthew执行GET请求+5 ,返回 text / plain
http://esv.to/Mt5
的回复。
I'm trying to build a javascript bookmarklet for a special URL shortening service we've built at http://esv.to for shortening scripture references (i.e. "Matthew 5" becomes "http://esv.to/Mt5". The bookmarklet is supposed to do a GET request to http://api.esv.to/Matthew+5, which returns a text/plain
response of http://esv.to/Mt5
.
书签本身的代码如下所示(为了便于阅读而扩展):
The code for the bookmarklet itself looks like this (expanded for readability):
var body = document.getElementsByTagName('body')[0], script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://esv.to/media/js/bookmarklet.js';
body.appendChild(script);
void(0);
来自的代码http://esv.to/med ia / js / bookmarklet.js
看起来像这样:
(function() {
function shorten(ref, callback) {
var url = "http://esv.to/api/" + escape(ref);
var req = new XMLHttpRequest();
req.onreadystatechange = function shortenIt() {
if ( this.readyState == 4 && this.status == 200 ) {
callback(req.responseText);
};
};
req.open( "GET", url );
req.send();
};
function doBookmarklet() {
var ref = prompt("Enter a scripture reference or keyword search to link to:", "")
shorten(ref, function (short) {
prompt("Here is your shortened ESV URL:", short);
});
};
doBookmarklet();
})();
从 http://esv.to 本身,书签正常工作。但是当在另一个页面上使用时,它不会。奇怪的是,当我看到来自Firebug的请求时,响应是 200 OK
,浏览器下载17个字节(返回字符串的长度),但响应体是空的!没有错误,只是XmlHttpRequest对象上的空responseText。
When called from http://esv.to itself, the bookmarklet works correctly. But when used on another page, it does not. The strange thing is, when I watch the request from Firebug, the response is 200 OK
, the browser downloads 17 bytes (the length of the returned string), but the response body is empty! No error is thrown, just an empty responseText on the XmlHttpRequest object.
现在,根据来自Bookmarklet的Ajax调用,GET不应违反相同的原始策略。这是一个错误吗?是否有解决方法?
Now, according to Ajax call from Bookmarklet, GET shouldn't violate the same origin policy. Is this a bug? Is there a workaround?
推荐答案
跨站点XMLHttpRequests只能在实现W3C的浏览器中完成跨源资源共享规范以及服务器是否返回相应的访问控制头(请参阅 MDC文章),例如:
Cross-site XMLHttpRequests can only be done in browsers that implement the W3C Cross-Origin Resource Sharing spec and if the server returns the appropriate access control headers (see MDC article), e.g.:
访问 - Control-Allow-Origin:*
但并非所有浏览器都实现此功能。进行跨站点请求的唯一可靠方法是使用 JSONP ,未经测试的例子:
But this is not implemented by all browsers. The only sure-fire way to do cross-site requests is to use JSONP, for (untested) example:
(function() {
function shorten(ref, callback){
var callbackFuncName = 'esvapiJSONPCallback' + (new Date()).valueOf();
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "http://esv.to/api/" + escape(ref) + "?callback=" + callbackFuncName;
window[callbackFuncName] = function(shorturl){
script.parentNode.removeChild(script);
window.callbackFuncName = null;
delete window[callbackFuncName];
callback(shorturl);
};
document.getElementsByTagName("head")[0].appendChild(script);
}
var ref = prompt("Enter a scripture reference or keyword search to link to:", "");
shorten(ref, function(shorturl) {
prompt("Here is your shortened ESV URL:", shorturl);
});
})();
当服务器看到回调
参数时然后需要返回 text / javascript
而不是 text / plain
,并且响应正文需要包含在调用提供的回调,例如:
When the server sees the callback
parameter it would then need to return text/javascript
instead of text/plain
, and the response body would need to be wrapped in an invocation of the provided callback, for example:
<?php
#... after $shorturl is set ...
if(isset($_GET['callback'])){
header('Content-Type: text/javascript');
$callback = preg_replace('/\W+/', '', $_GET['callback']); #sanitize
print $callback . "(" . json_encode($shorturl) . ");";
}
else {
header("Content-Type: text/plain");
print $shorturl;
}
?>
这篇关于书签中的XmlHttpRequest在GET上返回空的responseText?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!