【发布时间】:2018-03-02 00:47:00
【问题描述】:
使用 Laravel 的资源路由,我设置了一个 API 作为 React JS 应用程序的后端。我目前正在尝试访问“更新”方法。我正在使用 Javascript 的 fetch() 来完成此操作,因此它首先发出一个 OPTIONS 请求,然后发出 POST 请求(表单中有一个欺骗方法,将 _method 设置为 PATCH 而不是 - 这个显然不会影响最初的OPTIONS 调用)。同一页面也通过相同的方法向同一端点发出GET 请求,效果很好。
fetch() 电话如下。当然,这是 React,它是通过 Redux Saga 进程调用的,但实际的 fetch 在那里。
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})
}
还有 Laravel 路线:
Route::group(['middleware' => 'auth:api'], function() {
Route::resource('users', 'UserController');
}
我遇到了一个错误,其中对 URL 的初始 OPTIONS 请求返回了一个 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
这是来自 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
在 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
...
请求方法一模一样,请求URL一模一样,除了一个返回200,另一个返回404,无从得知。
此外,我应该将 另一个 POST 请求添加到 create 方法中,效果很好。
这可能是什么原因造成的?
尝试的解决方案
1. 我看到了这个问题 (React Native + fetch + API : DELETE request fails in App, works in 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');
Postman 请求仍然返回 200 OK,React 请求仍然返回 404 Not Found。
3. 尤里卡! 有点。根据另一个评论建议,我将来自 Chrome 的请求导出为 cURL 并将其直接导入 Postman - 也许我在复制标题时错过了一些东西。看来我做到了,因为现在邮递员请求也返回404!
在尝试禁用和/或启用导入的标头后,我确定问题是Origin 和Access-Control-Request-Method 标头的组合。如果只有 one 存在,则请求返回 200,但如果 both 存在,我会收到 404。
但是,这仍然给我留下了如何解决问题的问题。在这一点上,我想知道这个问题是否可能更像是一个 Laravel 问题 - IE,为什么对完全有效的资源路由的 OPTIONS 请求会返回 404。我假设是因为这些资源路由正在监听 PUT 或 PATCH但不是OPTIONS。
【问题讨论】:
-
很好的问题,但在问题中添加实际的
fetch调用可能有助于更好地理解。 -
也发布你的 Laravel 路线。
-
添加了 fetch() 示例和 Laravel 路由。
-
服务器的 CORS 设置怎么样?你能告诉我们这些吗?另外,在浏览器的开发工具中,除了 404 之外,您是否在控制台中看到任何错误?
-
遗憾的是,除了 404 本身之外,控制台中根本没有错误。添加了来自服务器的响应头。