A form that redirects a browser upon access through a regular form or an Ajax request - is this possible?

I have a webpage with a form. When the user submits the form, I want the server to redirect the browser to another page from the form action. Right now, I am doing this using the PHP header function to send the status code 302. It works fine.

I am trying to make the page on the server redirect the browser in the same way, regardless of whether it was sent normally (without Javascript) or through Ajax. I tried to do this by setting the location of the window to any URL in the Location header. I use jQuery and make the call as follows:

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

However, this did not work. Thinking about it, I realized that this is not surprising. In an Ajax request, the browser must transparently handle redirection responses, such as 302 code, before modifying readyState. When the full function starts, it searches for the location header at the final destination and does not find it.

As an experiment, I tried to send a 200 status code with the Location header. I tried the Ajax request and it worked fine. However, when I made a non-Ajax submit, this did not work. The browser went to the form action page and stayed there as if it were ignoring the Location header.

Is there a way to do the same page redirect in both cases, without having to know or care about whether the request is an Ajax request?

In this case, I tried the form in different browsers (IE8, IE7, IE6, Firefox 3.5, Chrome) with the same results every time. In addition, I am making a mail request so as not to attack the URL length limit in IE 2083.

+4
source share
8 answers

The HTTP 302 response is consumed silently by the XmlHttpRequest implementation (for example, the jQuery ajax function). This is a feature.

In the past, I decided to discover XmlHttpRequests and issue a "Content-Location" header (rather than a "Location" ). The most cross-library way to do this is to check the "X-Requested-With" http header in your server code (e.g. jQuery, Prototype, Mootools):

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

You still need the special code for your client code:

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

If the user is redirected no matter why Ajax? The whole point of Ajax, like this, is to make changes to the page without refreshing the page, so the technique you use seems a bit like creating a printer that is output to a chopper bin.

0
source

I would like to know more about your use case. As far as I understand, are you trying to get your application to load a page based on the Location header of an Ajax call inside it? I would ask why?

The HTTP header is not suitable for receiving this information. Doesn't your application essentially make a request that says, "Where will I redirect?" There is no reason why the Ajax response should actually respond with a 302 and Location header. Why not just respond with JSON or XML that contains the new URL?

Edit: Just re-read your penultimate paragraph. I'm not sure there is a good way to achieve what you want. The concept sounds broken. :)

0
source

Pass an extra parameter to your ajax request to make it easy to identify the type of request. When ajax - don't redirect - just send the destination URL, then redirect the client side in the ajax callback via location.href

like this:

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

The work will be completed:

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

Have you tried to use the error function instead of the full one?

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

jQuery sends any 3xx response to the error function. Perhaps the location heading will still be available at this point.

0
source

Why don't you require your "ajax" action to simply fill out the required form fields and submit the form instead? This way you get the same behavior as when sending manually.

0
source

Here is another option, although you will need some cross-browser tests:

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

The main disadvantages: the URL in the address bar does not change; may mess with the button / story back

Although I think the idea of ​​@crescentfresh is the way to go

0
source

All Articles