Laravel4 POST inexplicable redirect to GET

I am sure that another issue related to non-sleep. I send him as a sacrifice to Elder God Murphy: as soon as I reveal my misunderstanding so that everyone can see, I will surely find the answer itself, which otherwise would elude me within a few hours (in the form of further repentance, Then I will publish the answer) .

I have an HTML form that displays as

<form method="post" id="mysearch" action="/search/?uid=1701"> <input id="searchterm" type="text" name="query" /> </form> 

The form can be submitted via jQuery $.POST with the URL '/ search' and the data { uid: '1701', query: $('#searchterm').val() } , and it works.

If I press ENTER after typing something and thus override the jQuery view, the following will happen:

Answer 301 looks like Laravel4, added explicitly:

 HTTP/1.0 301 Moved Permanently Date: Thu, 28 Nov 2013 14:05:29 GMT Server: Apache X-Powered-By: PHP/5.4.20 Cache-Control: no-cache Location: http://development/search?uid=1701 Connection: close Content-Type: text/html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="refresh" content="1;url=http://development/search?uid=1701" /> <title>Redirecting to http://development/search?uid=1701</title> </head> <body> Redirecting to <a href="Redirecting to http://development/search?uid=1701">Redirecting to http://development/search?uid=1701</a> </body> </html> 

This is not the same as this question , because a redirect is expected, and this is an answer to the unwanted. Here he redirects himself, which is generated without a reason that I can (for now) see.

I suspect that for some reason I am running a "security redirect" described in this other answer that jQuery does not start (either because it puts everything in POST, while here I have one parameter in the URL address and the other in POST, or because jQuery uses XHR).

I thought it might be CSRF protection, but this particular route is not protected. As a last resort, I CSRF-protect the route and add the token to the form, even if it looks a bit like voodoo. Something vaguely similar happens in Rails .

Bypass

I have not one, not two, but three workarounds that neatly circumvented the question of why this is happening:

  • (the most violent) blocks the keyUp event on the form.
  • redirect form submit event in jQuery
  • (most transparent) redirects the specified event to $('#search-button').click()

... but I would like to do without a button at all (what I could do with jQuery) and without jQuery in general . And also to understand what is happening here. I'm 99% sure I'm missing something obvious.

Debugging

Now I will grep -r "Redirecting to" * entire source code of the framework (I expect to find something in Symfony/Components/HttpFoundation/ResponseRedirect ) and take it step by step from there.

+4
source share
1 answer

TL DR

make sure POST URLs do not end with a slash. - but Laravel 4.1 users first check the update below.

=======

When it works, it is not superstition - it is a science: - (

as soon as I expose my misunderstanding, so that everyone can see, I am guaranteed to find this answer myself, which otherwise would have eluded me for hours

I will argue that the Laravel4 HTML message could be a little more informative.

grep found the expected redirect source:

 grep -r "Redirecting to" * vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RedirectResponse.php: <title>Redirecting to %1$s</title> vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/RedirectResponse.php: Redirecting to <a href="%1$s">%1$s</a>. 

at this point, a simple backtrace discovered the origin, very early in the sprawl of Laravel4:

 bootstrap/start.php: ... | The first thing we will do is create a new Laravel application instance | which serves as the "glue" for all the components of Laravel, and is | the IoC container for the system binding all of the various parts. | */ $app = new Illuminate\Foundation\Application; $app->redirectIfTrailingSlash(); 

As soon as I saw redirectIfTrailingSlash , I realized that the two URLs submitted by the form and jQuery did not match:

 ... action="/search/?uid=1701"> <--- TRAILING SLASH AFTER 'search' ... url: '/search', <--- NO TRAILING SLASH data: { uid : 1701, query: $('#searchterm').val() }, ... 

Why this should happen, I do not quite understand, but the solution is terribly simple:

remove the slash from the POST action field.

(and make sure that .htaccess does not have a rule to treat the URL as a β€œdirectory” and add a backslash - but if that were the case, jQuery would also fail).

UPDATE

Apparently, the issue was addressed in Laravel 4.1. upgrade mentions

Removing trailing slash redirects

In bootstrap / start.php, delete the call to $ App-> redirectIfTrailingSlash (). This method is no longer needed because this functionality is now handled by the .htaccess file included in the framework.

Then replace the Apache.htaccess file with a new one that handles trailing slashes.

+13
source