【问题标题】:I can send GET requests to a local Laravel API, but all POST requests fail我可以向本地 Laravel API 发送 GET 请求,但所有 POST 请求都失败
【发布时间】:2021-02-06 15:29:12
【问题描述】:

我正在尝试设置一个基本的 Laravel API。我已经设置了一个 CORS 中间件,我正在从不同的(本地)域向 API 发出请求(即,aaa.host 是一个 React 前端,向 bbb.host Laravel API 后端发出 Axios 请求)。

所有 GET 请求都成功通过 API 并返回响应,但我尝试的任何 POST 请求都失败。我的理解是 CSRF 令牌仅在 Laravel 中用于 Web 请求,而不是 API 请求。因此,我无法理解我缺少什么以及为什么 POST 请求没有通过。如果我将 POST 路由更改为 GET 路由,它会立即起作用,因此它是 POST 路由这一事实似乎是问题所在。

下面是失败的 POST 请求在 Chrome 控制台中的示例:

我查看了 Laravel API 文档,但我不明白我缺少什么。有没有人有任何想法?另外,为了它的价值,我使用的是 Laravel 5.8.29。谢谢。


编辑:这是routes/api.php 的样子:

Route::middleware(['cors'])->group(function () {
    Route::post('/missing-subpath-on-purpose/item/create', 'SomeController@createItem');
});

同样,如果我将 Route::post 更改为 Route::get 并发出 Axios GET 请求而不是 POST,它可以正常工作。

【问题讨论】:

  • 路由是否在routes/api.php中声明?
  • 好的,你从 Postman 那里得到什么回应?
  • 我认为您路线上的飞行前请求也需要 OPTIONS 请求?
  • 好吧,因为它是跨域的,浏览器会发送一个预检请求来检查你是否被授权访问它。 Route::match(['OPTIONS','POST']) 有帮助吗?您必须在 CORS 中间件本身中处理选项请求。
  • @nice_dev,你一针见血。谢谢你。需要进行一些测试来验证,但浏览器停止了请求,因为 Content-Type 是application/json。那是浏览器的事情,这就是 Postman 工作的原因。我将 Axios 请求的默认 Content-Type 更改为 application/x-www-form-urlencoded 并且它有效。非常感谢。

标签: php laravel api authentication post


【解决方案1】:

非常感谢 nice_dev 发现了真正的问题并帮助我解决了它。事实证明 Laravel API 很好,并且从 Postman 向它发送 POST 请求也很好。

问题出在浏览器本身。如果您发送一个 Content-Type 为application/json 的 POST 请求,浏览器将强制发生两个请求,这会导致各种问题。 (我目前不知道这是什么原因,但我确信浏览器制造商有他们这样做的理由。)

不过,通过将浏览器中所有 Axios 请求的默认 Content-Type 更改为 application/x-www-form-urlencoded,它解决了我的问题。谢谢。


编辑:在尝试了更多之后,我意识到我确实想发出 application/json 请求,但这样做会导致上述 CORS 问题。

为了解决这个问题,我在 Laravel 中创建了以下 CORS 中间件:

<?php

    namespace App\Http\Middleware;

    use Closure;

    class Cors {
        public function handle($request, Closure $next) {
            header('Access-Control-Allow-Headers: *');
            header('Access-Control-Allow-Methods: *');
            header('Access-Control-Allow-Origin: *');

            return $next($request);
        }
    }

然后我将其添加到Kernel.php中的全局中间件中,如下:

protected $middleware = [
    ..., // Other middleware here.
    \App\Http\Middleware\Cors::class,
];

我犯的错误是 CORS 中间件不是全局中间件的一部分,而是导致问题的路由中间件。

【讨论】:

    猜你喜欢
    • 2018-07-05
    • 2020-08-28
    • 1970-01-01
    • 2018-04-22
    • 2015-07-25
    • 2020-04-06
    • 2013-03-21
    • 2012-09-22
    • 1970-01-01
    相关资源
    最近更新 更多