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 调用而失败的主要内容,如果未能解决你的问题,请参考以下文章

401 响应 CORS preflight OPTIONS 请求到 Spring Boot 服务器

CORS Preflight 请求是不是包含请求的标头?

RESTful WebService CORS Preflight Channel 未成功

CORS Preflight 403,但我有正确的标题

CORS preflight OPTIONS 请求从 Windows Authenticated web api 返回 401(未授权)

CORS Preflight 响应包括 Vary:Origin 和 Access-Control-Max-Age?