CGr*_*fin 12 apache laravel reactjs
使用Laravel的资源路由,我已经设置了一个API作为React JS应用程序的后端.我正在尝试访问"更新"方法.我正在使用Javascript fetch()来实现这一点,所以它OPTIONS首先发出一个请求,然后发出POST请求(表单中有一个方法欺骗,设置_method为PATCH- 这显然不会影响初始OPTIONS调用).同一页面也GET通过相同的方法向同一个端点发出请求,工作正常.
该fetch()呼叫在下面.当然,这是React,它是通过Redux Saga进程调用的,但实际的获取是在那里.
function postApi(values, endpoint, token) { // <-- values and endpoint are sent by the component, token is sent by a previous Saga function
return fetch(apiUrl + endpoint, { // <-- apiUrl is defined as a constant earlier in the file
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify(
values
)
}).then(handleApiErrors)
.then(response => response.json())
.catch((error) => {throw error})
}
Run Code Online (Sandbox Code Playgroud)
而Laravel路线:
Route::group(['middleware' => 'auth:api'], function() {
Route::resource('users', 'UserController');
}
Run Code Online (Sandbox Code Playgroud)
我遇到一个错误,其中对OPTIONSURL 的初始请求返回404错误,这是立即奇怪的,因为端点显然存在,刚刚在几秒钟之前查询的完全相同的端点,但我认为可能Laravel返回错误的错误,我使用了错误的方法.在放弃并在Postman中发出请求之前,我做了一些挖掘和调试,试图让请求变得正确.问题是:它在Postman中运行良好.
以下是服务器的响应头(请注意,允许任何访问源):
Access-Control-Allow-Origin:*
Cache-Control:no-cache, private
Connection:close
Content-Length:10
Content-Type:text/html; charset=UTF-8
Date:Thu, 21 Sep 2017 13:29:08 GMT
Server:Apache/2.4.27 (Unix) OpenSSL/1.0.2l PHP/7.0.22 mod_perl/2.0.8-dev Perl/v5.16.3
X-Powered-By:PHP/7.0.22
Run Code Online (Sandbox Code Playgroud)
这是从React JS应用程序(收到404错误的应用程序)发出的请求的请求标头:
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8,fr;q=0.6,ga;q=0.4
Access-Control-Request-Headers:authorization,content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:localhost
Origin:http://localhost:3000
Pragma:no-cache
Referer:http://localhost:3000/employees/edit/13
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Run Code Online (Sandbox Code Playgroud)
在Postman中,我设置了完全相同的请求标头,OPTIONS并向服务器发出了完全相同的请求.它工作正常!我收到了空的200响应.
为了确保,我仔细检查了Apache访问日志.果然:
...
::1 - - [20/Sep/2017:15:33:24 -0400] "OPTIONS /the/path/to/api/users/13 HTTP/1.1" 200 -
::1 - - [20/Sep/2017:15:40:26 -0400] "OPTIONS /the/path/to/api/users/13 HTTP/1.1" 404 10
...
Run Code Online (Sandbox Code Playgroud)
请求方法完全相同,请求URL完全相同,除了一个返回200,另一个返回404,没有可辨别的原因.
另外,我应该添加另一个 POST请求,该create方法,工作得很好.
可能是什么导致了这个?
经过精心设计的解决方案
1.我看到了这个问题(React Native + fetch + API:DELETE请求在App中失败,在Postman中运行),即使我正在运行Apache,而不是Nginx,我想我会尝试在请求中添加一个尾部斜杠URL.的OPTIONS请求现在返回一个错误301(永久移动).
2.我删除了斜线,继续试图解决.根据评论建议,我删除了自动路由生成并创建了自己的路由:
Route::get('/users', 'UserController@index');
Route::post('/users', 'UserController@create');
Route::put('/users/{user}', 'UserController@update');
Route::patch('/users/{user}', 'UserController@update');
Route::get('/users/{user}', 'UserController@show');
Run Code Online (Sandbox Code Playgroud)
邮递员请求仍然返回200 OK,并且React请求仍然返回404 Not Found.
3. 找到了!的种类.根据另一条评论建议,我将Chrome中的请求作为cURL导出并直接导入Postman - 也许我在复制标题时遗漏了一些内容.看来我做了,因为现在 Postman请求也返回404!
玩弄禁用和/或使进口头后,我已经确定问题是组合的Origin和Access-Control-Request-Method头.如果只有一个请求返回200,但如果两者都存在,我收到404.
但是,这仍然让我不知道如何解决问题.在这一点上,我想知道这个问题是否可能更像是一个Laravel问题 - IE,为什么OPTIONS对一个完全有效的资源路由的请求将返回404.我假设因为那些资源路由正在监听PUT或PATCH不监听OPTIONS.
既然您已经设置了 CORS,那么接下来您需要做的就是处理“预检”OPTIONS 请求。您可以使用中间件来做到这一点:
PreflightRequestMiddleware:
if ($request->getMethod() === $request::METHOD_OPTIONS) {
return response()->json([],204);
}
return $next($request);
Run Code Online (Sandbox Code Playgroud)
handle()在新建的中间件的方法中添加上述代码。将中间件添加到全局中间件堆栈中。
Access-Control-Allow-Methods另外,不要忘记在 CORS 设置中添加 OPTIONS 方法。
如需更多选项,请查看此内容。
回答:
阅读这篇文章。当浏览器向您的应用程序发送 OPTIONS 请求时,应用程序无法处理它,因为您仅为给定端点定义了 GET/POST/DELETE/PUT/PATCH 路由。
因此,为了使该路由能够处理预检请求:
Route::get('/users', 'UserController@index');
Run Code Online (Sandbox Code Playgroud)
它需要一个相应的 OPTIONS 路由:
Route::options('/users', 'UserController@options');
Run Code Online (Sandbox Code Playgroud)
注意:您将使用中间件在一个地方处理所有 OPTIONS 请求。但是,如果您将 OPTIONS 请求用于其他目的 - 请检查此答案中的第一个链接以获取更多选项。
| 归档时间: |
|
| 查看次数: |
3085 次 |
| 最近记录: |