Опубликовать данные в JsonP
Можно ли отправлять данные в JsonP? Или все данные должны быть переданы в querystring как запрос GET?
У меня есть много данных, которые мне нужно отправить в службу, перекрестный домен, и он слишком велик для отправки через querystring
Каковы варианты обойти это?
Ответы
Ответ 1
Невозможно выполнить асинхронный POST
для службы в другом домене из-за (вполне разумного) ограничения той же политики происхождения. JSON-P работает только потому, что вам разрешено вставлять теги <script>
в DOM, и они могут указывать в любом месте.
Вы можете, конечно, сделать страницу в другом домене действием обычной формы POST.
Изменить. Есть несколько интересных хаков, если вы готовы пойти на большие усилия вставляя скрытые <iframe>
и обманывая своими свойствами.
Ответ 2
Если вам нужно отправить много данных по междоменному. Обычно я создаю службу, которую вы можете вызвать в два этапа:
-
Сначала клиент делает FORM submit (сообщение разрешает перекрестный домен). Служба сохраняет ввод в сеансе на сервере (используя ключ GUID как ключ). (клиент создает GUID и отправляет его как часть ввода)
-
Затем клиент выполняет обычный script -inject (JSONP) в качестве параметра, который вы используете с тем же идентификатором GUID, который использовался в сообщении FORM. Служба обрабатывает ввод из сеанса и возвращает данные в обычном режиме JSONP. После этого сеанс уничтожается.
Это, конечно, полагается на то, что вы пишете сервер-сервер.
Ответ 3
Я знаю, что это серьезная некромантия, но я думал, что опубликую мою реализацию JSONP POST с помощью jQuery, которую я успешно использую для своего виджета JS (это используется для регистрации и входа в систему):
В принципе, я использую подход IFrame, как это предлагается в принятом ответе. То, что я делаю по-другому, после отправки запроса, я смотрю, если форму можно найти в iframe, используя таймер. Когда форма не может быть достигнута, это означает, что запрос вернулся. Затем я использую обычный запрос JSONP для запроса статуса операции.
Я надеюсь, что кто-то сочтет это полезным. Протестировано в >= IE8, Chrome, FireFox и Safari.
function JSONPPostForm(form, postUrl, queryStatusUrl, queryStatusSuccessFunc, queryStatusData)
{
var tmpDiv = $('<div style="display: none;"></div>');
form.parent().append(tmpDiv);
var clonedForm = cloneForm(form);
var iframe = createIFrameWithContent(tmpDiv, clonedForm);
if (postUrl)
clonedForm.attr('action', postUrl);
var postToken = 'JSONPPOST_' + (new Date).getTime();
clonedForm.attr('id', postToken);
clonedForm.append('<input name="JSONPPOSTToken" value="'+postToken+'">');
clonedForm.attr('id', postToken );
clonedForm.submit();
var timerId;
var watchIFrameRedirectHelper = function()
{
if (watchIFrameRedirect(iframe, postToken ))
{
clearInterval(timerId);
tmpDiv.remove();
$.ajax({
url: queryStatusUrl,
data: queryStatusData,
dataType: "jsonp",
type: "GET",
success: queryStatusSuccessFunc
});
}
}
if (queryStatusUrl && queryStatusSuccessFunc)
timerId = setInterval(watchIFrameRedirectHelper, 200);
}
function createIFrameWithContent(parent, content)
{
var iframe = $('<iframe></iframe>');
parent.append(iframe);
if (!iframe.contents().find('body').length)
{
//For certain IE versions that do not create document content...
var doc = iframe.contents().get()[0];
doc.open();
doc.close();
}
iframe.contents().find('body').append(content);
return iframe;
}
function watchIFrameRedirect(iframe, formId)
{
try
{
if (iframe.contents().find('form[id="' + formId + '"]').length)
return false;
else
return true;
}
catch (err)
{
return true;
}
return false;
}
//This one clones only form, without other HTML markup
function cloneForm(form)
{
var clonedForm = $('<form></form>');
//Copy form attributes
$.each(form.get()[0].attributes, function(i, attr)
{
clonedForm.attr(attr.name, attr.value);
});
form.find('input, select, textarea').each(function()
{
clonedForm.append($(this).clone());
});
return clonedForm;
}
Ответ 4
Ну, как правило, JSONP реализуется путем добавления тега <script>
к вызывающему документу, так что URL-адрес службы JSONP является "src". Браузер извлекает script источник с помощью транзакции HTTP GET.
Теперь, если ваша служба JSONP находится в том же домене, что и ваша вызывающая страница, тогда вы, вероятно, могли бы сжечь что-то вместе с простым вызовом $.ajax()
. Если это не в том же домене, то я не уверен, как это возможно.
Ответ 5
Вы можете использовать CORS Proxy, используя этот проект, Он направит весь трафик на конечную точку вашего домена и передаст эту информацию во внешний домен. Поскольку браузер регистрирует все запросы в одном домене, мы можем отправлять JSON.
ПРИМЕЧАНИЕ.. Это также работает с сертификатами SSL, хранящимися на сервере.
Ответ 6
Там (взломать) решение я сделал это много раз, вы сможете отправлять сообщения с JsonP.
(Вы сможете отправить форму, большую, чем 2000 char, чем вы можете использовать GET)
Клиентское приложение Javascript
$.ajax({
type: "POST", // you request will be a post request
data: postData, // javascript object with all my params
url: COMAPIURL, // my backoffice comunication api url
dataType: "jsonp", // datatype can be json or jsonp
success: function(result){
console.dir(result);
}
});
JAVA:
response.addHeader( "Access-Control-Allow-Origin", "*" ); // open your api to any client
response.addHeader( "Access-Control-Allow-Methods", "POST" ); // a allow post
response.addHeader( "Access-Control-Max-Age", "1000" ); // time from request to response before timeout
PHP:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');
Таким образом, вы открываете свой сервер для любого почтового запроса, вы должны его повторно защитить, предоставив идентификатор или что-то еще.
С помощью этого метода вы также можете изменить тип запроса с jsonp на json, оба работают, просто установите правильный тип содержимого ответа
JSONP
response.setContentType( "text/javascript; charset=utf-8" );
JSON
response.setContentType( "application/json; charset=utf-8" );
Пожалуйста, не то, что вы сервер больше не будете уважать SOP (та же политика происхождения), но кому это нужно?
Ответ 7
Возможно, вот мое решение:
В вашем javascript:
jQuery.post("url.php",data).complete(function(data) {
eval(data.responseText.trim());
});
function handleRequest(data){
....
}
В вашем url.php:
echo "handleRequest(".$responseData.")";