Laravel 7 中对 localhost:3000 的 CORS 支持
Posted
技术标签:
【中文标题】Laravel 7 中对 localhost:3000 的 CORS 支持【英文标题】:CORS support for localhost:3000 in Laravel 7 【发布时间】:2020-06-19 22:25:22 【问题描述】:在此处发布之前,我确保在网上查找可能的问题解决方案。
我使用 Nuxt s-s-r
作为前端,使用 Laravel 7 作为后端 API,它现在具有本机 CORS 实现。我的前端应用程序在http://localhost:3030
运行,api 在http://gaminghub.test
运行。
这是我在最新版 laravel 自带的cors.php
里的:
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => false,
'max_age' => false,
'supports_credentials' => true,
];
使用邮递员,这是向http://gaminghub.test/api/products?category=play-card
发送get请求时返回的内容:
"data": [
"id": 1,
"name": "Xiaomi",
"price": 2000000,
"description": "Best value for money",
"slug": "xiaomi"
],
"links":
"first": "http://gaminghub.test/api/products?page=1",
"last": "http://gaminghub.test/api/products?page=2",
"prev": null,
"next": "http://gaminghub.test/api/products?page=2"
,
"meta":
"current_page": 1,
"from": 1,
"last_page": 2,
"path": "http://gaminghub.test/api/products",
"per_page": 1,
"to": 1,
"total": 2
nuxt.config.js 包括:
/*
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
axios:
baseURL: "http://gaminghub.test/api",
credentials: true
,
product.vue
包含以下内容以检索数据:
<script>
export default
data()
return
product: null
,
async asyncData(params, app)
let res = await app.$axios.$get(`products/?category=$params.slug`)
return
product: res.data
,
</script>
所以,基本上,当我点击每个类别时,他们会向api/products?category=clicked-category-slug
发送一个获取请求,这会导致控制台出现以下错误:
Access to XMLHttpRequest at 'http://gaminghub.test/api/products/?category=play-card' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
网络请求头包含以下内容:
Request Headers
Provisional headers are shown
Accept: application/json, text/plain, */*
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9nYW1pbmdodWIudGVzdFwvYXBpXC9hdXRoXC9sb2dpbiIsImlhdCI6MTU4MzU3MjQ4MiwiZXhwIjoxNTgzNTc2MDgyLCJuYmYiOjE1ODM1NzI0ODIsImp0aSI6ImdYY1Q3WGRSVnFXdUpocFIiLCJzdWIiOjMsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.t4JLsLLE6WIFZp67hbafZl8YTLlzN2WyQVw11mETMNQ
Referer: http://localhost:3000/categories/play-card
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/80.0.3987.132 Safari/537.36
当我重新加载浏览器时,错误消失并返回预期的数据。 Nuxt 正在universal s-s-r
模式下运行。
我需要一些指导来了解可能导致此问题的原因。我一定是错过了什么
【问题讨论】:
我猜products/?category=...
中的额外斜线会导致自动重定向到products?category=...
。检查响应标头以确认,或尝试删除斜杠。
就是这样。我怎么可能没有注意到这一点。非常感谢!
【参考方案1】:
“预检请求不允许重定向”错误。通常在服务器向客户端发送“位置”响应标头时发生。浏览器不喜欢这样,因此会引发错误。因此,您在 url /api/products?category=play-card 上的 laravel 控制器可能会发送 Location 标头,我不确定。 例如,您可以做些什么来调试此问题,即在您请求此 url 时使用 Postman 检查发送给客户端的标头。
希望这会对你有所帮助。
PS:我是在这里回答问题的初学者,所以可能不是正确的答案。
【讨论】:
【参考方案2】:这就是我使用 react 16 和 laravel 7 的方式
在我的 Controller 中,我只是使用了welcomeController 作为存储在 app\http 中的示例
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class WelcomeController extends Controller
public function show()
return view('welcome');
public function post(Request $request)
// extra data that may come from a database
// or a token or whatever your external component needs
$post = [
'title' => 'my title',
'content' => 'Lorem, ipsum dolor sit amet consectetur adipisicing elit. Hic velit, harum neque adipisci praesentium quo voluptate laudantium ipsam optio provident accusamus modi nobis, facere atque iure perferendis corporis? Quam, distinctio.'
];
$response = array_merge($request->all(), $post);
return json_encode($response);
在 /app/http/Middleware 中
添加文件 Cors.php。添加以下代码
<?php
namespace App\Http\Middleware;
use Closure;
class Cors
public function handle($request, Closure $next)
return $next($request)
->header('Access-Control-Allow-Origin', 'http://localhost:3000')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, X-Token-Auth, Authorization');
接下来在 ./routes 中构建您的 api,如下所示
// the order or the middleware matter so make sure that
// cors middleware is first before the api middleware
Route::middleware('cors:api')->post('/post', 'WelcomeController@post');
在 app/config/cors.php 中,保持这个文件不变
[
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
在受保护的 $routeMiddleware 数组中的 app/Http/Kernel.php 中附加一个新的键/值对,参见下面的示例:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'cors' => \App\Http\Middleware\Cors::class, // add route middleware
];
然后在您的 UI 中,您可以测试传入的数据是否通过,我使用 react 但我使用原生 javascript Fetch api 来发布帖子。下面是调用并将信息呈现给 DOM 的组件
import React, Component from 'react';
class ConnectToApi extends Component
state =
data: []
componentDidMount()
this.handleGetData();
handleGetData = async () =>
fetch('http://laravel-api.local/api/post',
method: 'post',
mode: 'cors',
headers: new Headers(
'Accept': 'application/json',
'Content-Type': 'application/json',
),
body: JSON.stringify(
name: 'John',
surname: 'Doe',
)
)
.then(response => response.json())
.then(data =>
const state = Object.assign(, this.state)
state.data.push(data);
this.setState(state);
)
.catch(error => console.log(error));
render()
console.log(this.state.data);
return <div>
<header>
<h1>
data
</h1>
</header>
<p>Modified data</p>
this.state.data.length === 0 && <p>loading data...</p>
this.state.data.length > 0 && this.state.data.map((value, index) =>
return (
<div key=index>
<p>name: value.name</p>
<p>surname: value.surname</p>
<p>title: value.title</p>
<p>Content <br/><br/> value.content</p>
</div>
)
)
</div>
export default ConnectToApi;
然后在 app.js 中只有
import React from 'react';
import logo from './logo.svg';
import './App.css';
import ConnectToApi from './connectToApi'
function App()
return (
<div className="App">
<ConnectToApi />
</div>
);
export default App;
【讨论】:
以上是关于Laravel 7 中对 localhost:3000 的 CORS 支持的主要内容,如果未能解决你的问题,请参考以下文章