通过JSONP在CDN上的静态JSON文件

Mik*_*ghe 10 json jsonp cdn

我有大量的JSON格式的静态/很少变化的数据.为了提高我的ASP.NET MVC应用程序性能,我想将它们转移到CDN(Amazon Cloud Front).

但是,当我这样做时,跨域策略启动并且jQuery进行HTTP OPTIONS方法调用而不是HTTP GET,并且亚马逊拒绝了"403 Forbidden"响应的请求.

JSONP可能是解决此问题的方法,但由于文件是静态的并且在CDN上,因此无法将JSON包装在自定义函数中.但是我可以用已知的函数名重新创建它们.例如:

{"LineDetails":{"LineNo":"3109","DbId":9 ....}}
Run Code Online (Sandbox Code Playgroud)

我可以这样做:

JsonWrapping({"LineDetails":{"LineNo":"3109","DbId":9 ....}});
Run Code Online (Sandbox Code Playgroud)

所有文件的"JsonWrapping"函数名称都相同.

如果jQuery包含在如上所示的相同函数名中,jQuery是否可以通过JSONP下载JSON数据?我对jQuery JSONP的阅读是jQuery为JSONP请求创建了一些自定义的一次性使用函数名称.这可以被覆盖吗?

谢谢你的帮助.

Chr*_*ini 5

jQuery JSONP的最佳实践

在文档的$.getJSON$.ajax,该JSONP节指出,您可以用明确地设置回调函数名称jsonpCallback配置属性.因此,如果你想JsonWrapping(...)成为jquery在jsonp响应中所期望的函数,你可以将事情重新组合起来:

$.ajax({
    url: 'http://blah.com/blah.json'????????????????????????,
    dataType: 'jsonp',
    cache: true,
    jsonpCallback: 'JsonWrapping'
})
.done(function(r) {
    status.text('It worked.');
})
.fail(function (a, b, c) {
    status.text('It failed.');
});????????????????????????
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,jsonp响应中的预期回调函数现在JsonWrapping()是jQuery将为您发出的,通过调用.done()上面的响应,并在自身之后进行清理 - 比硬编码JsonWrapping到页面更清晰.

硬编码和命名建议的危险

需要考虑的一件重要事情是,如果你计划在一个页面上进行许多jsonp调用,并且你的jsonp包装函数在jsonp文件中是硬编码的,那么你应该至少改变你的包装函数,比如filename.否则,您将创建异步问题.例如假设你有这个代码:

function jsonp(url) {
    return $.ajax({
        url: url,
        dataType: 'jsonp'
        cache: true,
        jsonpCallback: 'JsonWrapping'
    });
}

jsonp('http://cdn.mine/one.jsonp')
.done(...);

jsonp('http://cdn.mine/two.jsonp')
.done(...);
Run Code Online (Sandbox Code Playgroud)

其中一个jsonp调用将在另一个之前完成 - 不可能知道哪个 - 并且jQuery处于一个不可能的情况,它无法知道.done()哪个响应哪个响应.因此,您将获得正确调用的页面加载,以及数据纵横交错的页面加载.解决方案是改变文件名,如:

function jsonp(url, wrapper) {
    return $.ajax({
        url: url,
        dataType: 'jsonp'
        cache: true,
        jsonpCallback: wrapper
    });
}

jsonp('http://cdn.mine/one.jsonp', 'one')
.done(...);

jsonp('http://cdn.mine/two.jsonp', 'two')
.done(...);
Run Code Online (Sandbox Code Playgroud)

所以来自two.jsonp的响应需要看起来像:

two({...json object here...})
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

这个答案开头的调用将使jQuery通过GET请求URL,如下所示:

http://blah.com/blah.json?callback=JsonWrapping
Run Code Online (Sandbox Code Playgroud)

并期待这作为回应:

JsonWrapping({...object here...})
Run Code Online (Sandbox Code Playgroud)

cache: true上面列出的是因为这是在CDN上,因此,大概不会经常改变.如果cache: true省略,jQuery会插入第二个用于缓存清除的查询字符串参数,例如:

http://blah.com/blah.json?callback=JsonWrapping&_=1365175172440
Run Code Online (Sandbox Code Playgroud)

这可能会破坏CDN的重点.第二个查询字符串参数的目标是确保数据不从浏览器缓存加载,并且当它到达服务器(在这种情况下为CDN)时,查询字符串是唯一的,这意味着它也会破坏其缓存.

在您使用CDN的场景之外,有些情况下需要jQuery的默认功能:例如,当您想要将POST功能模拟到另一个域而不违反Same-Origin策略时,具有此缓存清除功能的jsonp可以为你完成这件事.

如果您正在与之交谈的服务器在查询字符串中需要"回调"之外的其他内容来指定响应中回调函数的名称,则可以使用jsonpconfig属性 - 例如jsonp: 'myname',它会让您:

http://blah.com/blah.json?myname=JsonWrapping
Run Code Online (Sandbox Code Playgroud)


Bar*_*den 4

我刚刚发现这在某种程度上是可能的。我是这样解决的:

$(document).ready(function(){
    $.getJSON("http://example.com/staticjsonfile.json",function(data){
    //callback function isn't here
    }
});
function JsonWrapping(data){
    //It's really here
    alert(data);
}
Run Code Online (Sandbox Code Playgroud)

这并不理想,因为您失去了与触发 Ajax 请求的事件的绑定。所以需要一些黑客技术。然而,它有点完成工作。我非常乐意接受更好的解决方案。