Відповіді:
Неможливо зробити асинхронну POST
послугу в іншому домені через (цілком розумне) обмеження тієї ж політики походження . JSON-P працює лише тому, що вам дозволяється вставляти <script>
теги в DOM, і вони можуть вказувати куди завгодно.
Можна, звичайно, зробити сторінку на іншому домені дією звичайної форми POST.
Редагувати : Там є кілька цікавих хак , якщо ви готові докласти чимало зусиль, вставляючи приховані <iframe>
s та розмовляючи зі своїми властивостями.
POST
запити в інші домени, якщо і цей домен, і ваша веб-переглядач CORS
. Але цілком вірно це POST
і JSONP
не сумісні.
<script>
тегів, які вказують на інший домен. Єдиний спосіб виконання POST-запитів у браузері - це через HTML форми або XMLHttpRequest.
Якщо вам потрібно надіслати багато даних міждоменним. Зазвичай я створюю послугу, яку можна зателефонувати за два етапи:
Спочатку клієнт виконує форму подання (розміщення крос-домену). Служба зберігає вхід в сеанс на сервері (використовуючи GUID як ключ). (клієнт створює GUID і надсилає його як частину вводу)
Тоді клієнт виконує звичайний введення сценарію (JSONP) як параметр, яким ви користуєтесь тим самим GUID, який ви використовували у публікації FORM. Сервіс обробляє вхід із сеансу та повертає дані у звичайному режимі JSONP. Після цього сеанс знищується.
Звичайно, це спирається на те, що ви пишете сервер-бекенд.
XMLHttpRequest
взагалі не слід брати участь. Відповідь Пер використовується для подання POST запиту, а потім введення елемента скрипта для отримання GET-запиту.
Я знаю, що це серйозна некромантія, але я думав, що опублікую свою реалізацію 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;
}
Загалом, JSONP реалізується додаванням <script>
тегу до викликового документа таким чином, що URL-адреса служби JSONP є "src". Браузер отримує джерело сценарію за допомогою транзакції HTTP GET.
Тепер, якщо ваша служба JSONP знаходиться в тому ж домені, що і ваша сторінка для виклику, ви, ймовірно, можете щось обмотати разом із простим $.ajax()
дзвінком. Якщо це не в одному домені, то я не впевнений, як це було б можливо.
CORS
то це буде можливим, поки браузер його також підтримує. У цих випадках ви скористаєтеся звичайними, JSON
а не простими JSONP
.
Ви можете використовувати проксі-сервер CORS, використовуючи цей проект . Це спрямовуватиме весь трафік до кінцевої точки вашого домену та передаватиме цю інформацію на зовнішній домен. Оскільки браузер реєструє всі запити на один і той же домен, ми можемо розміщувати JSON. ПРИМІТКА. Це також працює з SSL-сертифікатами, що зберігаються на сервері.
Є (хак) рішення, яке я робив це багато разів, ви зможете публікувати повідомлення з JsonP. (Ви зможете опублікувати формуляр, більший за 2000 знаків, ніж ви можете використовувати 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 (таку ж політику походження), але кого це хвилює?
<script>
тегів у свій HTML DOM (чорт ви можете навіть використовувати їх у додатках для настільних ПК, скажімо, ви хотіли робити кілька запитів JSON на одному сервері та хотіли використовувати ім'я функції наприклад, ідентифікатор відстеження запиту).
Можливо, ось моє рішення:
У вашому javascript:
jQuery.post("url.php",data).complete(function(data) {
eval(data.responseText.trim());
});
function handleRequest(data){
....
}
У вашому url.php:
echo "handleRequest(".$responseData.")";