Форма, которая делает переадресацию браузера при доступе посредством обычной формы или запроса Ajax – возможно ли это?

У меня есть веб-страница с формой. Когда пользователь отправляет форму, я хочу, чтобы сервер переадресовал браузер на другую страницу из действия формы. Прямо сейчас, я делаю это, используя функцию заголовка PHP для отправки кода состояния 302. Он работает нормально.

Я пытаюсь сделать страницу на сервере перенаправлением браузера таким же образом, независимо от того, была ли она отправлена ​​нормально (без Javascript) или через Ajax. Я попытался сделать это, установив местоположение окна на любой URL-адрес в заголовке Location. Я использую jQuery и делаю вызов следующим образом:

$.ajax({ url: this.action, type: "POST", data: getFormData(this), complete: function(request) { window.location.assign(request.getResponseHeader("Location")); } }); 

Однако это не сработало. Подумав об этом, я понял, что это не удивительно. В запросе Ajax браузер должен прозрачно обрабатывать ответы перенаправления, такие как 302 кода, перед изменением readyState. Когда запускается полная функция, он ищет заголовок местоположения в конечном месте назначения и не находит его.

В качестве эксперимента я попытался отправить код состояния 200 с заголовком Location. Я попробовал запрос Ajax, и он работал нормально. Однако, когда я сделал не-Ajax submit, это не сработало. Браузер перешел на страницу действия формы и остался там, как будто игнорировал заголовок Location.

Есть ли способ сделать одну и ту же переадресацию страницы в обоих случаях, без необходимости знать или заботиться о том, является ли запрос Ajax-запросом?

В случае, если это имеет значение, я пробовал форму в разных браузерах (IE8, IE7, IE6, Firefox 3.5, Chrome) с одинаковыми результатами каждый раз. Кроме того, я делаю почтовый запрос, чтобы не нападать на ограничение длины URL-адреса 2083 символов IE.

Ответ HTTP 302 потребляется молча по реализациям XmlHttpRequest (например, функция ajax jQuery). Это особенность.

Способ, которым я решил это в прошлом, – обнаружить XmlHttpRequests и выпустить заголовок "Content-Location" (а не заголовок "Location" ). Самый кросс-библиотечный способ сделать это – проверить заголовок http-заголовка "X-Requested-With" в вашем серверном коде (например, jQuery, Prototype, Mootools):

 if (@$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { header('Content-Location: ' . $redirect_url); } else { header('Location: ' . $redirect_url); } 

Вам по-прежнему нужен специальный код вашего клиентского кода:

 $.ajax({ // ... complete: function(xhr) { var redirect_url = xhr.getResponseHeader("Content-Location"); if (redirect_url) { window.location = redirect_url; } } }) 

Если пользователь перенаправляется независимо от того, почему Ajax? Вся суть Ajax, как это, заключается в том, чтобы внести изменения в страницу без обновления страницы, поэтому используемая вами техника кажется немного похожей на создание принтера, который выводится в бункер для измельчителя.

Я хотел бы узнать больше о вашем случае использования. Насколько я понимаю, вы пытаетесь заставить ваше приложение загружать страницу на основе заголовка «Местоположение» вызова Ajax внутри него? Я бы спросил, почему?

Заголовок HTTP не подходит для получения этой информации. Разве ваше приложение по существу не делает запрос, в котором говорится: «Куда я буду перенаправлять?». Нет никакой причины, по которой ответ Ajax на самом деле должен отвечать заголовком 302 и «Location». Почему бы просто не ответить на него JSON или XML, который содержит новый URL-адрес?

Изменить: просто перечитайте свой предпоследний абзац. Я не уверен, что есть хороший способ добиться того, чего вы хотите. Концепция звучит нарушена. 🙂

Передайте дополнительный параметр вашему запросу ajax для упрощения идентификации типа запроса. Когда ajax – не перенаправлять – просто отправьте целевой URL, а затем перенаправьте клиентскую сторону в обратном вызове ajax через location.href

как это:

 $ .post ('/ controller / action', {formdata}, function (redirect_to) {
     location.href = redirect_to;
 });

Будет «завершена» работа:

 $.ajax({ type: frm.attr('method'), url: frm.attr('action'), data: frm.serialize(), complete: complete(xhr, status) { window.location.assign(xhr.getResponseHeader("Location")); } }); 

Вы пытались использовать функцию ошибки вместо полной?

 $.ajax({ url: this.action, type: "POST", data: getFormData(this), error: function(request) { if(request.status == 302) window.location.assign(request.getResponseHeader("Location")); } }); 

jQuery отправляет любой ответ 3xx на функцию ошибки. Возможно, заголовок «Местоположение» по-прежнему будет доступен на этом этапе.

Почему бы вам не потребовать, чтобы ваше действие «ajax» просто заполнило необходимые поля формы и вместо этого отправил форму? Таким образом, вы получите то же поведение, что и при отправке вручную.

Вот еще один вариант, хотя вам нужно будет сделать несколько кросс-браузерных тестов:

 complete: function(request) { if(request.status == 200) { var doc = document.open(request.getResponseHeader('Content-Type')); doc.write(request.responseText); doc.close(); } } 

Основные недостатки: URL-адрес в адресной строке не изменяется; может испортиться с помощью кнопки / истории

Хотя я думаю, что идея @ crescentfresh – это способ пойти