Статические файлы JSON через CDN через JSONP
У меня есть большое количество статических/редко изменяющихся данных в формате 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. Может ли это быть отменено?
Спасибо за вашу помощь.
Ответы
Ответ 1
Я только узнал, что это возможно. Я решил это так:
$(document).ready(function(){
$.getJSON("http://example.com/staticjsonfile.json",function(data){
//callback function isn't here
}
});
function JsonWrapping(data){
//It really here
alert(data);
}
Это не идеально, поскольку вы теряете привязку к событию, которое вызвало запрос Ajax. Поэтому требуется хакерство. Тем не менее, он как бы справляется со своей задачей.
Я был бы очень открыт для лучшего решения.
Ответ 2
Лучшая практика для 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 в другом домене, не нарушая политику "один и тот же", jsonp с этим кешем функция busting может сделать это для вас.
Если сервер, о котором вы говорите, ожидает чего-то другого, кроме "callback" в querystring для указания имени функции обратного вызова в ответе, вы можете использовать свойство конфигурации jsonp
- например, jsonp: 'myname'
вы:
http://blah.com/blah.json?myname=JsonWrapping