Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Redirect Ajax Requests #5647

Closed
tristanlins opened this issue Apr 13, 2013 · 12 comments
Closed

Redirect Ajax Requests #5647

tristanlins opened this issue Apr 13, 2013 · 12 comments
Labels
Milestone

Comments

@tristanlins
Copy link
Contributor

First of all, why you not do a "normal" redirect on Ajax Requests?
see https://github.com/contao/core/blob/develop/system/modules/core/library/Contao/Controller.php#L1998
and https://github.com/contao/core/blob/develop/system/modules/core/library/Contao/Controller.php#L1971

Ajax requests will follow redirects if the server send them to the client. I think it is useless to not redirect ajax requests to the new location.

Now the problem: For me it is not only useless, it breaks my script code.
The reason is, that I'm unable to detect the redirect. You only send the new location, but not an information (a prefix or special header) that the response is a redirect. Most ajax calls expect JSON, but contao only send plain text. This break most ajax calls.

In my eyes, there must be several changes (and I mean, all of them) to make this usable for developers:

  1. Don't send plain url without information about a redirect. Send Location: <url> instead of just <url> OR/AND send a header, for example X-Ajax-Location: <url>.
    Then I'm able to detect this IS a redirect response.

  2. Check the Accept header, if the header container application/json (or one of the other json mime types), send a json response instead of plain text like { "location": "<url>" }.

  3. Add a parameter and header (headers are easier to globaly set in Mootools or jQuery) that allow to bypass this sh**. For example

// Ajax request
if (\Environment::get('isAjaxRequest') && !\Input::get('follow-location'))
{
    echo $strLocation;
    exit;
}

// bypass follow-location parameter, to keep it if the next request is also a redirect!
if (\Input::get('follow-location'))
{
    $strLocation .= (strpos($strLocation, '?') !== false ? '&' : '?') . 'follow-location=1';
}

header('Location: ' . $strLocation);
exit;
  1. Make the default behavior configurable in the system settings. As I said before, there is no reason to enforce ajax-redirects by sending the new url to the client instead of forward them.

I would provide some code, but first I wan't to discuss this problem.

@backbone87
Copy link
Contributor

Do we talk about FE or BE?

@tristanlins
Copy link
Contributor Author

My script was in FE, but is the same in BE because the redirect code is the same ;-)

@backbone87
Copy link
Contributor

Recently I unset the header upon that contao decides whether or not the request is made via ajax, so I can handle everything by myself in the normal rendering process.

@leofeyer
Copy link
Member

Ajax requests will follow redirects if the server send them to the client

True, however, if you are in an iframe (modal window), there is no way to redirect the outer window with a PHP header() directive. Therefore, the XHR response – which is a JSON response BTW – contains a JavaScript command which is then executed by the Request.Mootao class.

@leofeyer
Copy link
Member

More information about the issue: #3516

It seems, however, that we did not change the two lines of code you have referenced above.

@leo-unglaub
Copy link

Most ajax calls expect JSON, but contao only send plain text.

Thats not true at all. Just because some jQuery guys think JSON is everything is does not mean that this is true. An AJAX request has like every other HTTP request no default mime type. It gets always set. Because you also can return an octet stream in an AJAX call.

About the issue itself, redirects are a fundamental part of HTTP and there is no reasion for Ajax calls not to follow them. Because in the end it's just another HTTP call. :)

@leofeyer
Copy link
Member

I have fixed the code in d7af406 so the redirect gets executed properly. (The page won't reload if the Ajax response contains a 303 header.)

Now shall we try to send a particular header together with the JS code, so you can catch the event?

@tristanlins
Copy link
Contributor Author

True, however, if you are in an iframe (modal window), there is no way to redirect the outer window with a PHP header() directive.

But an iframe request is not an ajax request?!

Therefore, the XHR response – which is a JSON response BTW – contains a JavaScript command which is then executed by the Request.Mootao class.

But I don't use Request.Mootao? I make regular Ajax requests with jQuery like $.get(url, handle).
And an HTML script tag as you implemented in d7af406 is not a JSON response... O.o

I don't say you should break the current behavior, but there should be a way for the developer to manipulate it. The patch d7af406 makes no difference to me in terms of the original problem.

@leofeyer
Copy link
Member

That's why I asked

Now shall we try to send a particular header together with the JS code, so you can catch the event?

:)

@tristanlins
Copy link
Contributor Author

Now shall we try to send a particular header together with the JS code, so you can catch the event?

Yes, please! :-)

@leofeyer
Copy link
Member

leofeyer commented May 1, 2013

This does not work as expected. The MooTools request class only triggers the onSuccess() method if the servers sends a 2xx header (which is perfectly right of course), but not if a 302 or 403 header is sent. Therefore here's my proposal:

  • Instead of sending a JavaScript string, we should exit with a HTTP header.
  • The MooTao class should respond to the header in the onFailure() method.

However, this change will have to wait until Contao 3.2.

@leofeyer
Copy link
Member

Fixed in 6f8d8ac.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants