Laravel 4 POST无法解释重定向到GET

时间:2013-11-28 14:40:20

标签: php jquery symfony redirect laravel-4

另一个我没有睡觉的问题,我敢肯定。我把它作为牺牲给老上帝墨菲发布:一旦我揭露了我的所有人的蠢事,我就保证自己找到答案,否则我将无法回答几个小时(通过进一步的忏悔,我会发布答案)。

我有一个HTML表单,呈现为

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

表单可以通过jQuery $.POST提交,网址为“/ search”,数据为{ uid: '1701', query: $('#searchterm').val() } ,但

如果我在输入内容后按ENTER键,从而覆盖jQuery提交,则会发生以下情况:

  • 按预期向服务器发出POST。
  • Route::post('/search', function() {... 被调用。
  • a 301 Moved Permanently is return
  • GET with search parameters lost将发布到“重定向”指定的网址
  • 很明显,搜索失败了。

301响应看起来像Laravel4的内容,明确补充说:

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 question不同,因为预期会有重定向,而的答案是不受欢迎的。在这里,重定向本身是无缘无故地生成的(现在)可以看到。

我怀疑由于某种原因我触发了this other answer中描述的“安全重定向”,这不是由jQuery触发的(因为它将所有内容放在POST中,而在这里我有一个参数POST中的URL和另一个,或者因为jQuery使用XHR)。

我原以为这可能是CSRF的防御,但是这条特定的路线并没有被屏蔽。作为最后一个资源,我将CSRF保护路由并将令牌添加到表单中,即使它看起来有点像伏都教给我。 Rails中似乎发生了一些模糊相似的东西。

的变通方法

我没有一个,而不是两个,但三个的解决方案巧妙地回避了为什么是上述问题:

  • (最残忍)阻止表单中的keyUp事件。
  • 将表单的 submit 事件重定向到jQuery
  • (最透明)将上述事件路由到$('#search-button').click()

...但是我想完全没有按钮(我可以用jQuery做)和完全没有jQuery 。同时了解这里发生了什么。我99%肯定我错过了一些明显的东西。

调试

我现在要grep -r "Redirecting to" *整个框架源代码(我期望在Symfony/Components/HttpFoundation/ResponseRedirect中找到一些内容)并从那里逐步完成。

1 个答案:

答案 0 :(得分:14)

TL; DR

确保POST网址不以斜杠结尾。 - 但Laravel 4.1用户首先检查以下更新。

=======

当它有效时,它不是迷信 - 它是科学: - (

  

一旦我暴露了所有人的蠢事,我就保证自己找到   这个答案可能会让我无法忍受数小时

我认为Laravel4的HTML消息本来可以提供更多信息。

grep按预期找到了重定向的来源:

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>.

在那一点上,一个简单的回溯在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();

当我看到redirectIfTrailingSlash时,我意识到表单和jQuery 发送的两个网址不一样

... action="/search/?uid=1701">   <--- TRAILING SLASH AFTER 'search'

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

为什么会发生这种情况我不太了解,但解决方案非常简单:

从POST操作字段中删除斜杠。

(并确保.htaccess没有规则将URL视为“目录”而添加斜杠 - 但如果有,则jQuery也会失败。)

更新

显然,Laravel 4.1对此事进行了审核。 upgrade提及

  

删除重定向尾随斜杠

     

在bootstrap / start.php文件中,删除对的调用   $ APP-&GT; redirectIfTrailingSlash()。不再需要此方法   此功能现在由.htaccess文件处理   框架。

     

接下来,将Apache .htaccess文件替换为新的.htaccess文件   处理尾部斜杠。