Axios CORS/Preflight 因 Laravel 5.4 API 调用而失败

Posted

技术标签:

【中文标题】Axios CORS/Preflight 因 Laravel 5.4 API 调用而失败【英文标题】:Axios CORS/Preflight failing with Laravel 5.4 API call 【发布时间】:2018-03-01 12:28:42 【问题描述】:

我在使用 Laravel 5.4 和我的使用 Axios 处理请求的 React 应用程序时遇到问题。

这是我遇到的错误。

这是我失败的预检响应的请求标头。

这是预检后失败的请求:

这是我的axios请求配置:

let req = axios(
    method: "GET",
    url: https://api.vendorgraphs.com/queryStringHere
    headers: 
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + accessToken
    
);

需要注意的一个有趣的事情是它使用 HTTPS 协议指定端点。我的应用程序上的类似请求正在正常工作,但这是唯一失败的请求。是不是因为使用了查询字符串?

请求作为 GET 请求到达 API 端点。我正在使用 Laravel 和 laravel-cors 包来处理我的 cors 请求。

这是我对 CORS 的配置:

这是在我的 Kernel.php

protected $middleware = [
    \Barryvdh\Cors\HandleCors::class,
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

还有我在配置文件夹中的 cors.php

return [
    'supportsCredentials' => false,
    'allowedOrigins' => ['*'],
    'allowedHeaders' => ['*'],
    'allowedMethods' => ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"],
    'exposedHeaders' => [],
    'maxAge' => 0,
];

我可以明显看到网络选项卡中的预检失败。但我不明白的是为什么我会收到混合内容错误而不是 405 或其他一些 HTTP 状态代码。当我使用 HTTPS 显式设置 url 时,它说我正在使用 HTTP 协议请求端点,这似乎很奇怪。

我已经在这个问题上停留了一段时间,并且可以在这个问题上使用一些见解。 似乎很多人都对 OPTIONS 预检有“类似”的问题。如果请求的方法是 OPTIONS,我已经完成了创建一个只返回 200 HTTP 状态代码的中间件之类的事情。但这也没有用。将请求更改为 Axios 的 OPTIONS 并将 Laravel 上的路由更改为:

Route::options("/api/endpoint", controller@method);

也没有用。我只是不明白为什么它会重定向到 HTTP 协议并返回混合内容错误,而这似乎与 CORS 无关,但预检请求失败,这表明它是一个 CORS 问题。任何和所有的见解都是值得赞赏的。

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %REQUEST_FILENAME !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %REQUEST_FILENAME !-d
    RewriteCond %REQUEST_FILENAME !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %HTTP:Authorization .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%HTTP:Authorization]

    RewriteCond %HTTPS !=on
    RewriteCond %HTTP:X-Forwarded-Proto ^http$
    RewriteRule .* https://%HTTP_HOST%REQUEST_URI [R=301,L]
</IfModule>

【问题讨论】:

使用 htaccess 配置编辑。这可能是弹性豆茎问题吗? 【参考方案1】:

您看到的问题的原因是,服务器本身将https URL 重定向到http

$ curl -I 'https://api.vendorgraphs.com/api/dealershipvendorleads/?id=3,4&startDate=2017-4&endDate=2017-8'

HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=iso-8859-1
Date: Wed, 20 Sep 2017 15:33:50 GMT
Location: http://api.vendorgraphs.com/api/dealershipvendorleads?id=3,4&startDate=2017-4&endDate=2017-8
Server: Apache
Connection: keep-alive

注意301 状态码,以及带有http://api.vendorgraphs.com/…Location 标头

这意味着,如果浏览器将其作为混合内容阻止(如您所见),您将无法从安全上下文(https 页面)向该 API 端点发出跨域请求。

所以这并不是真正的 CORS 问题,而是纯粹的混合内容问题。

【讨论】:

我没有看到我在任何地方重定向到 HTTP。我正在使用弹性 beanstalk 来托管 laravel 应用程序。这可能是个问题吗? 对,并没有重定向到任何地方——而是运行api.vendorgraphs.com的服务器正在重定向你的请求:它正在接收你的https://api.vendorgraphs.com请求(安全https)并重定向它到http://api.vendorgraphs.com(不安全的http)。这就是答案中的 301 状态代码和 Location 标头所表示的。而且您无法从自己的角度解决此问题。 我不能在 .htaccess 文件中写一个重写规则来强制 https 吗? 我想我的问题是,为什么这只发生在这个特定的请求中?是使用查询字符串吗?除了 ID 参数在这个参数中有多个值之外,我还有其他类似的请求。查询字符串和内容类型:'application/json' 是否与此错误有关?我应该将它们作为不同的内容类型发送吗? @DanielPark 答案是?

以上是关于Axios CORS/Preflight 因 Laravel 5.4 API 调用而失败的主要内容,如果未能解决你的问题,请参考以下文章