Статические файлы JSON через CDN через JSONP - PullRequest
10 голосов
/ 21 июля 2010

У меня есть большое количество статических / редко меняющихся данных в формате JSON. Чтобы повысить производительность приложений ASP.NET MVC, я бы хотел переместить их в CDN (Amazon Cloud Front).

Однако, когда я делаю это, междоменная политика запускается, и jQuery вызывает HTTP-метод OPTIONS вместо HTTP GET, и Amazon отклоняет запрос с ответом «403 Forbidden».

JSONP может быть способом обойти это, но поскольку файлы статичны и в CDN нет способа обернуть JSON в пользовательскую функцию. Однако я могу воссоздать их, обернутые с известным именем функции. Например:

{"LineDetails":{"LineNo":"3109","DbId":9 ....}}

Я могу сделать что-то вроде:

JsonWrapping({"LineDetails":{"LineNo":"3109","DbId":9 ....}});

Имя функции "JsonWrapping" будет одинаковым для всех файлов.

Возможно ли, чтобы jQuery загружал данные JSON через JSONP, если они заключены в то же имя функции, как показано выше? Мое чтение jQuery JSONP состоит в том, что jQuery создает некоторое произвольное имя функции одноразового использования для запроса JSONP. Может ли это быть отменено?

Спасибо за вашу помощь.

Ответы [ 2 ]

5 голосов
/ 03 мая 2012

Рекомендация для jQuery JSONP

В документах для $.getJSON и $.ajax раздел jsonp отмечает, что вы можете явно указать имя функции обратного вызова с помощью jsonpCallbackсвойство config.Поэтому, если вы хотите, чтобы 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.');
});​​​​​​​​​​​​​​​​​​​​​​​​

В приведенном выше примере ожидаемая функция обратного вызова внутри ответа jsonp имеет видтеперь JsonWrapping(), который jQuery будет выдавать для вас, ответит, позвонив .done() выше и очистив после себя - намного чище, чем жесткое кодирование JsonWrapping на странице.

Опасности жесткого кодированияи предложения по именованию

Важно учитывать, что если вы планируете иметь много вызовов jsonp на одной странице, а ваши функции переноса jsonp жестко запрограммированы в файлах jsonp, вам следует как минимум изменить свою функцию переноса.чем-то вроде имени файла.В противном случае вы создаете проблему асинхронности.Например, предположим, что у вас был такой код:

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(...);

Один из этих вызовов 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(...);

Так что ответ от two.jsonp должен выглядеть следующим образом:

two({...json object here...})

Как это работает

Вызов в начале этого ответа заставит jQuery запросить URL через GET следующим образом:

http://blah.com/blah.json?callback=JsonWrapping

И ожидать это как ответ:

JsonWrapping({...object here...})

Я включил cache: true выше, потому что это находится в CDN, и, следовательно, предположительно не должно меняться очень часто.Если вы пропустите cache: true, jQuery вставит второй параметр строки запроса, предназначенный для очистки кэша, например:

http://blah.com/blah.json?callback=JsonWrapping&_=1365175172440

, который может испортить точку CDN.Целью второго параметра querystring является обеспечение того, чтобы данные не загружались из кэша браузера, и когда он попадает на сервер (в данном случае CDN), строка запроса уникальна, то есть он также отключает свой кэш.

За пределами вашего сценария, в котором вы используете CDN, бывают ситуации, когда желаемая функциональность по умолчанию в jQuery: например, когда вы хотите смоделировать функциональность POST в другом домене, не нарушая политику Same-Origin, jsonp с этимФункция очистки кеша может сделать это за вас.

Если сервер, с которым вы разговариваете, ожидает что-то иное, чем «обратный вызов» в строке запроса для указания имени функции обратного вызова в ответе, вы можете использоватьjsonp свойство config - например, jsonp: 'myname' даст вам:

http://blah.com/blah.json?myname=JsonWrapping
4 голосов
/ 23 июля 2010

Я только что узнал, что это как-то возможно.Я решил это так:

$(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);
}

Это не идеально, так как вы теряете связь с событием, вызвавшим запрос Ajax.Таким образом, требуется взлом.Тем не менее, это своего рода работа сделана.Я был бы очень открыт для лучшего решения.

...