php - Form that makes browser redirect when accessed by either a regular form submit or an Ajax request - is this possible? - St

I have a web page with a form. When the user submits the form, I want the server to make the browser re

I have a web page with a form. When the user submits the form, I want the server to make the browser redirect to a different page from the form action. Right now, I am doing this by using PHP's header function to send a 302 status code. 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 submitted normally (without Javascript) or via Ajax. I tried to do this by setting the window location to whatever URL is in the Location header. I am using jQuery, and doing a call like this:

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

However, that didn't work. After thinking about it, I realized that this is not very surprising. In an Ajax request, the browser is supposed to transparently handle redirect responses such as 302 codes before changing the readyState. When the plete function runs, it is looking for the Location header in the final destination and not finding it.

As an experiment, I then tried sending a 200 status code with a Location header. I tried the Ajax request and it worked fine. However, when I did the non-Ajax submit, it didn't work. The browser went to the form action page and stayed there, like it was ignoring the Location header.

Is there any way to make the same page redirect in both cases, without the server having to know or care whether the request is an Ajax request?

In case this matters, I tried the form in various browsers (IE8, IE7, IE6, Firefox 3.5, Chrome) with similar results each time. Also, I am doing a post request to avoid bumping into IE's 2083-character URL length limit.

I have a web page with a form. When the user submits the form, I want the server to make the browser redirect to a different page from the form action. Right now, I am doing this by using PHP's header function to send a 302 status code. 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 submitted normally (without Javascript) or via Ajax. I tried to do this by setting the window location to whatever URL is in the Location header. I am using jQuery, and doing a call like this:

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

However, that didn't work. After thinking about it, I realized that this is not very surprising. In an Ajax request, the browser is supposed to transparently handle redirect responses such as 302 codes before changing the readyState. When the plete function runs, it is looking for the Location header in the final destination and not finding it.

As an experiment, I then tried sending a 200 status code with a Location header. I tried the Ajax request and it worked fine. However, when I did the non-Ajax submit, it didn't work. The browser went to the form action page and stayed there, like it was ignoring the Location header.

Is there any way to make the same page redirect in both cases, without the server having to know or care whether the request is an Ajax request?

In case this matters, I tried the form in various browsers (IE8, IE7, IE6, Firefox 3.5, Chrome) with similar results each time. Also, I am doing a post request to avoid bumping into IE's 2083-character URL length limit.

Share Improve this question edited Nov 17, 2023 at 20:38 CommunityBot 11 silver badge asked Sep 22, 2009 at 22:15 Elias ZamariaElias Zamaria 101k34 gold badges121 silver badges152 bronze badges
Add a ment  | 

8 Answers 8

Reset to default 5

HTTP 302 response are consumed silently by XmlHttpRequest implementations (e.g. jQuery's ajax function). It's a feature.

The way I've solved this in the past is to detect for XmlHttpRequests and issue a "Content-Location" header (rather than a "Location" header). The most cross-library way of doing this is to check for the "X-Requested-With" http header in your server-side code (jQuery, Prototype, Mootools among others set this):

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

You still need to special-case your client-side code:

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

If the user is getting redirected regardless, why the Ajax? The whole point of Ajax like this is to make changes to the page without a page refresh, so the technique you're using seems a little like building a printer that outputs into a shredder hopper.

I'd like to know more about your use-case for this. From what I understand your trying to get your application to load a page based on the 'Location' header of an Ajax call within it? I'd ask why?

An HTTP header doesn't seem to be the right place to get that information from. Isn't your application essentially making a query that says "Where shall I redirect to?". There's no reason the Ajax response actually has to respond with a 302 and a 'Location' header. Why not just have it respond with JSON or XML which contains the new URL?

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

Pass additional parameter to your ajax request for easy identify type of request. When ajax - do not redirect - just send target url, then redirect client side in ajax callback via location.href

like this:

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

Will "plete" work:

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

    }
});

Did you try using the error function instead of plete?

$.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. Maybe the 'Location' header will still be available at this stage.

Why not have your "ajax action" simply fill in the needed form fields and submit the form instead? This way you'll get exactly the same behavior as when submitting by hand.

Here is another option although you will need to do some cross browser tests:

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

Major drawbacks: URL in address bar doesn't change; could mess with back button/history

Although I think @crescentfresh's idea is the way to go

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745212332a4616917.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信