因此,我将Laravel 5.8
用作API
视图的ReactJS
。
我已经创建了一个“ cors”中间件,将其注册在 Kernel.php 文件中,并在iam使用的api路由上iam使用它。我使用GET请求进行了测试,并且可以正常工作,但是当我使用POST请求进行测试时,出现了cors错误:
从原点“ http://localhost:8000/api/posts”到“ http://localhost:3000”的获取操作已被CORS策略阻止:对预检请求的响应未通过访问控制检查:否“ Access-Control-Allow-来源的标头出现在请求的资源上。如果不透明的响应满足您的需求,请将请求的模式设置为“ no-cors”,以在禁用CORS的情况下获取资源。
所以我在我的 api.php (“ /routes/api.php”)上:
Route::get('/posts', 'PostController@index')->middleware('cors');
Route::post('/posts', 'PostController@store')->middleware('cors');
我的 cors.php 中间件:
<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
}
}
在我的 Kernel.php (“ /app/Http/Kernel.php”)上,我用'cors'
中间件更新了“ $ routeMiddleware”数组
'cors' => \App\Http\Middleware\Cors::class,
现在在我的React项目中,我的 api.js (我在其中编写了发出请求的代码):
// get Posts
export const getPosts = () => {
return fetch('http://localhost:8000/api/posts')
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.log(err));
}
// create new post
export const createPost = (post) => {
return fetch('http://localhost:8000/api/posts',
{
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify(post)
})
.then(res => res.json())
.then(res => console.log(res));
}
我不理解为什么在尝试Get request
时一切正常,但是在尝试Post Request
时却得到CORS error
。有人已经有这个问题了吗?
答案 0 :(得分:1)
对我来说,唯一解决此问题的方法是将cors中间件类放在$middleware
中Kernel.php
数组的顶部
protected $middleware = [
\App\Http\Middleware\Cors::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
这是我正在使用的cors中间件
<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$response->header("Access-Control-Allow-Origin","*");
$response->header("Access-Control-Allow-Credentials","true");
$response->header("Access-Control-Max-Age","600"); // cache for 10 minutes
$response->header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT"); //Make sure you remove those you do not want to support
$response->header("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, X-Requested-With, Application");
return $response;
}
}
希望有一天会有帮助。
答案 1 :(得分:1)
我通过使用FormData而不是JSON.stringfy解决了这个问题:
所以,我改变了:
Bitmap bitmap = Bitmap.createBitmap(24, 24, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.MAGENTA);
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
getWindow().setBackgroundDrawable(bitmapDrawable);
收件人:
let data = JSON.stringify({firstname:'John', familyname: 'Doe'});
完整的代码如下:
let data = new FormData();
data.append('firstname','John');
data.append('lastname','Doe');
答案 2 :(得分:1)
因此,当我在 api.php 中使用自己的 CORS 中间件而不使用水果蛋糕 (barryvdh/laravel-cors) 时,我遇到了同样的问题,并花了数小时进行调试并找出问题所在。
经过数小时的调试和挫折,我发现当您在组中使用中间件时,它不会立即得到应用。
当您发送请求时,laravel 会读取 api.php 并“注册”所有路由和中间件并“记住”它们,而无需实际执行它们。在它“注册”所有这些(读取整个 api.php
文件)之后,它执行一个函数,在该函数中它输入来自 URL 的路径和请求中使用的 HTTP 方法,然后它开始查找路由匹配 URL 和 HTTP 方法,找到一个后,它执行该路由所在的中间件,然后执行控制器方法。
例如,对于您的代码,当您向 GET
发送 /api/posts
请求时,它匹配资源方法 index
,然后执行中间件 cors
,因此它可以工作并从您的控制器返回数据。
当您向 POST
发送 PUT
、DELETE
、PATCH
或 /api/posts
请求时,浏览器首先发送 OPTIONS
请求,所以 laravel 会“注册”所有路由,然后使用 URL 和 HTTP 方法执行“匹配”(现在是 OPTIONS
)。
但是没有具有 OPTIONS
方法的路由,resources
也没有 OPTIONS
方法,因此由于没有具有 {{1} 方法的路由} 方法,laravel 不匹配任何内容,因此它不会执行那些您最终处理 OPTIONS
方法的中间件。
OPTIONS
示例
api.php
“匹配”函数称为 Route::post('/posts', 'PostController@store')->middleware('cors');
,它位于 findRoute
。
vendor/laravel/framework/src/Illuminate/Routing/Router.php
当您使用 /**
* Find the route matching a given request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Routing\Route
*/
protected function findRoute($request)
{
$this->current = $route = $this->routes->match($request);
$this->container->instance(Route::class, $route);
return $route;
}
记录 $route
,然后发出 error_log(json_encode($route), 0);
请求,然后查看错误日志时,您可以看到成功的“匹配”并且它应用了 {{1 }} 控制器:
GET
但是当您发送 cors
请求时,会发生这种情况:
{"uri":"api\/posts","methods":["GET","HEAD"],"action":{"middleware":["cors"],"uses":"App\\Http\\Controllers\\PostController@index","controller":"App\\Http\\Controllers\\PostController@index","namespace":null,"prefix":"api","where":[]},"isFallback":false,"controller":null,"defaults":[],"wheres":[],"parameters":[],"parameterNames":[],"computedMiddleware":null,"compiled":{}}
在那里你可以看到实际上发送了 POST
方法(因为浏览器首先发送了一个 {"uri":"api\/posts","methods":["OPTIONS"],"action":{"uses":{}},"isFallback":false,"controller":null,"defaults":[],"wheres":[],"parameters":[],"parameterNames":[],"computedMiddleware":null,"compiled":{}}
方法)并且没有匹配到并且没有应用中间件,因此 OPTIONS
请求失败了CORS 错误 (OPTIONS
)
PUT
数组中的中间件被应用之后 Laravel 成功地将路由与路径和 HTTP 方法匹配,因为不同的路由可以有不同的中间件。Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
数组中的中间件(全局中间件)在 Laravel 开始注册和匹配路由之前应用。要解决此问题,您必须在 $routeMiddleware
数组中使用全局中间件来处理 $middleware
方法。您可以只使用处理它的 Fruitcake 一个,然后您可以在 $middleware
中使用您自己的 CORS 中间件,该中间件可以根据您的喜好设置不同的标头(例如,不同路由/组/前缀的不同 Allowed Origins .
答案 3 :(得分:0)
将您的中间件更改为此
<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$domain = parse_url($_SERVER['HTTP_REFERER']);
$host = '*';
if (isset($domain['host'])) {
$host = $domain['host'];
}
return $next($request)
->header('Access-Control-Allow-Origin', $host)
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
}
}
但是一旦投入生产,您就需要通过环境变量来限制允许的主机。
您也可以只使用barryvdh/laravel-cors
Link here