代码之家  ›  专栏  ›  技术社区  ›  am05mhz

Laravel 5.5“MethodNotAllowedHttpException”的原因是什么?

  •  2
  • am05mhz  · 技术社区  · 6 年前

    在你投票反对我就这个错误发表另一个问题之前,或者把这个标记为重复或其他什么,我的问题有点不同

    以下是导致此错误的已知原因:

    • 表单和路由不匹配,例如:表单使用 POST ,路由使用 GET
    • CSRF令牌不匹配/丢失:否 csrf 元字段或表单字段中的标记

    我已经检查了这两个原因:

    • 确保了形式和路线的匹配
    • 试图禁用 CSRF 评论验证 CSRF 验证中间件 app/Http/Kernel.php ,但仍有此错误(这是正确的方法吗?)

    基本上,这两个是我知道的,也是我在这里搜索时发现的。

    所以我的问题是:

    除了这两个原因之外,是否还有其他情况会导致此错误?

    如果你想看我的代码:

    路由/web.php

    Route::post('/export', [
        'as' => 'export.csv',
        'uses' => 'ToolsController@export'
    ]);
    

    HTML表单

        <form class="form-inline" action="{{ route('export.csv') }}" id="csv_export" method="post">
            {{ csrf_field() }}
            <input type="hidden" name="type" value="site_maps">
            <input type="hidden" name="id" value="{{ request('id') }}">
            <button type="submit" class="btn btn-primary">Export to CSV</button>
        </form>
    

    app/http/controllers/toolscontroller.php

    namespace App\Http\Controllers;
    
    class ToolsController extends Controller
    {
        public function export(Request $request)
        {
             // some function
        }
    }
    

    附加细节:

    有一个 XSRF-TOKEN Cookie集,已尝试在浏览器上删除它,但它再次显示。

    更新

    请求头

    POST /export HTTP/1.1
    Host: somehost.com
    Connection: keep-alive
    Content-Length: 68
    Pragma: no-cache
    Cache-Control: no-cache
    Origin: http://somehost.com
    Upgrade-Insecure-Requests: 1
    Content-Type: application/x-www-form-urlencoded
    Save-Data: on
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Referer: http://somehost.com/map/47
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.9,id-ID;q=0.8,id;q=0.7
    Cookie: sso_token_33=--some-key--; XSRF-TOKEN=--some-token--; somehost_session=--some-cookie--
    

    表单数据

    _token=--some-other-token--&type=site_maps&id=47
    

    无路由分组

    更新

    我有一个奇怪的例子,如下图所示,浏览器正确地发送了一个post请求,但laravel似乎将其视为get请求, 是否有任何apache设置会导致这种行为?

    post vs get

    路线表:

    +--------+----------+----------------+----------------+-------------------------------------------------+--------------+
    | Domain | Method   | URI            | Name           | Action                                          | Middleware   |
    +--------+----------+----------------+----------------+-------------------------------------------------+--------------+
    |        | POST     | export         | export.csv     | App\Http\Controllers\ToolsController@export     | web          |
    |        | GET|HEAD | map/{id}       | pages.show     | App\Http\Controllers\PagesController@show       | web          |
    |        | GET|HEAD | tree           | pages.tree     | App\Http\Controllers\PagesController@tree       | web          |
    +--------+----------+----------------+----------------+-------------------------------------------------+--------------+
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Travis Britz    6 年前

    MethodNotAllowedHttpException 只有 当方法与路由定义不匹配时引发。这意味着所有这些条件都是真实的:

    • 请求http动词(get、post等)不在匹配路由定义的允许方法列表中
    • _method 表单域未发送
    • 一个 X-HTTP-Method-Override 标题未发送
    • 方法不是 OPTIONS

    有些路由定义允许多种方法。例如, Route::get() 将get和head定义为可接受。

    潜在原因

    错误实际上很明显(请求使用了错误的方法),但原因有时更微妙。从最明显到最不明显开始,以下是常见的原因:

    • 向定义为的路由发送get请求 Route::post()
    • 定义删除、修补等路由并忘记 _方法 HTML表单中的字段
    • 请求错误的路由(输入错误、复制/粘贴错误)-检查开发人员工具的“网络”选项卡并比较 请求头 :path :method 的uri和method列 php artisan route:list
    • 定义内部的路由 Route::group() 可能添加了URL前缀,如 api/ admin/ -这将与 route:list
    • 以错误的顺序定义路由,例如 users/active 需要在之前定义 users/{user} 否则 {user} 路由变量将匹配 'active'

    如果你仍然没有看到问题,试着修补你的道路 从“网络”选项卡中的请求头复制 开发人员工具:

    $ php artisan tinker
    >>> $uri = '/your/requested/path'
    >>> $method = 'POST'
    >>> app('router')->getRoutes()->match(app('request')->create($uri, $method))
    => Illuminate\Routing\Route {#191
     +uri: "...",
        ...
    

    如果一切 仍然 看起来是正确的,现在应该开始检查您的apache/nginx/iis配置,特别是查找重定向/重写情况,例如添加/删除子域(如www)或https。

    或者,如果引发了相同的异常,请尝试不使用$method并仔细检查响应:

    >>> app('router')->getRoutes()->match(app('request')->create($uri))
    

    CSRF令牌有问题 导致此错误。相反,这会抛出一个不同的异常,比如 TokenMismatchException ,或者在某些情况下可能是授权错误。同样,cookie问题不应该导致这样的错误。

    因为这是一个laravel/symfony异常,所以 应该 排除iis/apache/nginx问题(除非重写规则正在拦截请求)。例如,IIS在默认情况下禁用了某些谓词(Put、Delete等),但在这种情况下会显示IIS405错误页。