抱歉,还没有人回答这个问题。我曾经试图密切关注堆栈溢出,但我变得懒惰:-P。这是一个非常有趣的问题。
标准重定向 (301/302) 使用与原始请求相同的动词,除非原始请求是 aPOST
有趣的是,这种行为并不是真正的意图。重定向应该使用与原始请求相同的请求方法,但POST
->GET
重定向的意图是如此普遍,以至于大多数浏览器都添加了此行为,即使它违反了原始定义。然而,有些人真的希望 aPOST
保持 a POST
,现在这取决于实施。事实上,这变得如此糟糕,以至于 HTTP 添加了响应状态 307/308,它总是重定向为相同的 http 动词(即POST
-> POST
),甚至认为这已经是旧的官方行为但那艘船已经航行了。这意味着POST
-> GET
,但是DELETE
->DELETE
是 301/302 的实际行为。
这可以在以下一行中演示($_
在这些一行中是控制器):
perl -Mojo -E 'del "/delete" => sub { $_->redirect_to("/") }; any "/" => { inline => q[I got a <%= $c->req->method %>] }; app->start' get -r -v -M DELETE /delete
DELETE /delete HTTP/1.1
Host: 127.0.0.1:62690
Accept-Encoding: gzip
User-Agent: Mojolicious (Perl)
Content-Length: 0
HTTP/1.1 302 Found
Date: Sun, 18 Sep 2016 03:25:58 GMT
Server: Mojolicious (Perl)
Location: /
Content-Length: 0
DELETE / HTTP/1.1
Content-Length: 0
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:62690
Accept-Encoding: gzip
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 5
Date: Sun, 18 Sep 2016 03:25:58 GMT
Server: Mojolicious (Perl)
I got a DELETE
您可以看到,由于我的/
路由处理了我们得到响应的所有方法,但是请求是DELETE
. 我看到在您的应用程序中,您重定向到另一个命名路由,其 url 也处理DELETE
. 这是您困惑的根源,因为您实际上是在测试中结束的。如果我正确阅读了您的代码,您的重定向是有效的DELETE /backups/<<id>>
-> 。DELETE /backups
现在,与想要保留POST
as的人POST
相反,您在这里想要的是相反的,您想要重定向 from DELETE
toGET
因为您试图显示不是原始资源的响应。这是鲜为人知的 303 响应的定义行为,其中任何请求方法都被重定向到GET
. 的确,这是早期浏览器应该坚持的,而不是打破 302。
在以下示例中,我将响应代码显式修改为 303。
$ perl -Mojo -E 'del "/delete" => sub { $_->res->code(303); $_->redirect_to("/") }; any "/" => { inline => q[I got a <%= $c->req->method %>] }; app->start' get -r -v -M DELETE /delete
DELETE /delete HTTP/1.1
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:62716
Accept-Encoding: gzip
Content-Length: 0
HTTP/1.1 303 See Other
Location: /
Content-Length: 0
Server: Mojolicious (Perl)
Date: Sun, 18 Sep 2016 03:27:19 GMT
DELETE / HTTP/1.1
User-Agent: Mojolicious (Perl)
Accept-Encoding: gzip
Content-Length: 0
Host: 127.0.0.1:62716
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Server: Mojolicious (Perl)
Content-Length: 5
Date: Sun, 18 Sep 2016 03:27:19 GMT
I got a DELETE
但是,糟糕,这仍然是一个DELETE
!这是因为 Mojo::UserAgent 中存在一个错误,因此它不能正确处理 303。我建议您仍然对代码进行更改,因为浏览器似乎可以正确处理 303。然而,由于 Mojo::UserAgent 支持 Test::Mojo,您的测试还不能测试该行为。修复后,您将看到它正常工作,就像我在本地分支中的示例一样:
$ perl -Ilib -Mojo -E 'del "/delete" => sub { $_->res->code(303); $_->redirect_to("/") }; any "/" => { inline => q[I got a <%= $c->req->method %>] }; app->start' get -r -v -M DELETE /delete
DELETE /delete HTTP/1.1
Content-Length: 0
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:64924
Accept-Encoding: gzip
HTTP/1.1 303 See Other
Date: Sun, 18 Sep 2016 04:59:37 GMT
Location: /
Server: Mojolicious (Perl)
Content-Length: 0
GET / HTTP/1.1
Content-Length: 0
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:64924
Accept-Encoding: gzip
HTTP/1.1 200 OK
Date: Sun, 18 Sep 2016 04:59:37 GMT
Content-Type: text/html;charset=UTF-8
Server: Mojolicious (Perl)
Content-Length: 12
I got a GET
要了解有关重定向响应类型的更多信息,请参阅https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection