有没有办法从子域加载json?

时间:2010-10-19 01:58:02

标签: javascript jquery json

我喜欢在CDN a static.mydomain.com上存储一些.json文件。说实话,static.mydomain.com是Amazon S3存储桶前面的CNAME。

我理解这违反了JavaScript安全模型。是否有建议的解决方法或设计?我已经看到服务器端的东西建议像一个PHP脚本通过cURL或file_gets_contents()来吸收数据,但这是一个相当蹩脚的方法。有没有办法从外部服务器加载JSON而不会太过于hacky?

===

更新:这是让我相信它是子域的跨域问题的思路。

当我在Chrome中访问某个页面(例如static.mydomain.com/json/file.json)时,它会显示为纯文本。当我在Firefox中访问该页面时,它会尝试让我将.json保存为下载。

我在Firebug中看到了一个奇特的结果: 200响应,没有响应体。 alt text

我无法通过浏览器记录直接标头;我的Firefox HTTP标头插件在强制下载之前不记录任何内容。但是这里是通过这个jQuery snippit加载时的标题(值得注意的是,下面的警报不会触发):

jQuery.get("https://static.mydomain.com/json/file.json",
   function(data){
     alert("Data: " + data);
   }
);

响应标头

x-amz-id-2 wSVtjlvFj5ffOtg7ZbKqKw8PexqlzJic7+PxSk975/FcDUnshSV2CiUP2oPWR8yK
x-amz-request-id 8AD81565A783988D
Date Tue, 19 Oct 2010 00:07:22 GMT
Expires Sat, 17 Oct 2015 22:25:37 GMT
Last-Modified Mon, 18 Oct 2010 01:08:13 GMT
Etag "2f1c7adcc1a7b0fd8fc8ce1478e0bf81"
Content-Type application/json
Content-Length 85966
Server AmazonS3

请求标题

Host static.mydomain.com
User-Agent Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept application/json, text/javascript, */*; q=0.01
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Referer http://mydomain.com/directory/referrer.html
Origin http://mydomain.com

虽然标题在我看来很好,没有响应主体要么通过jQuery获取,发布或其他任何我可以抛出的内容。将内容类型设置为application / json,text / javascript和text / plain时,我看到相同的结果。

任何人都可以解释这种行为吗?我认为我必须在S3方面做错事,但它可能是JavaScript中的跨域问题还是我可以排除跨子域问题?

2 个答案:

答案 0 :(得分:4)

使用jQuery.getJSON而不是.get。 .get使用XHR,它在域(甚至子域)之间不友好。 getJSON使用一个可以工作的JSONP请求。

http://api.jquery.com/jQuery.getJSON/

您需要修改JSONP响应的JSON数据。它需要一个定义回调的参数。 jQuery创建一个随机函数作为回调函数,因此,如果您的整个观点是将其用作CDN,则无法动态更改响应中的回调名称。

您可以通过将正确的参数传递给jQuery.ajax来使用静态回调: http://api.jquery.com/jQuery.ajax/

dataType: 'json' //(.getJSON is just a shorthand for .ajax with this paraeter set)
jsonpCallback: 'myStaticCallbackName' // Lets the client know what callback to expect from the server.

然后你的回答应该是这样的:

myStaticCallbackName({"foo": "bar"});

答案 1 :(得分:2)

您可以使用JSONP或使用子域的绝对路径(这假设子域位于同一服务器上,它必须是这样)。也就是说,你应该使用/ home / path_to_subdomain /等而不是https:blah blah,它应该可以工作。

JSONP也是一个很好的解决方案,但如果你能提供子域的绝对路径,它可能有点过分。