完全相同的请求返回200邮递员,但404返回反应应用程序

时间:2017-09-20 19:59:23

标签: apache laravel reactjs

使用Laravel的资源路由,我已经设置了一个API作为React JS应用程序的后端。我正在尝试访问“更新”方法。我正在使用Javascript的fetch()来完成此操作,因此首先发出一个OPTIONS请求,然后发出POST请求(表单中有一个方法欺骗,设置{{1}转而使用_method - 这显然不会影响最初的PATCH调用。同样的页面通过相同的方法向同一个端点发出OPTIONS请求,效果很好。

GET电话如下。当然,这是React,它是通过Redux Saga进程调用的,但实际的获取是在那里。

fetch()

Laravel路线:

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})
}

我遇到了一个错误,其中对网址的初始Route::group(['middleware' => 'auth:api'], function() { Route::resource('users', 'UserController'); } 请求返回了OPTIONS错误,这个错误很快就出现了,因为端点显然存在,刚刚查询了完全相同的端点几秒钟前,但我想也许Laravel可能会返回错误的错误,而且我使用了错误的方法。在放弃并在Postman中发出请求之前,我做了一些挖掘和调试,试图让请求变得正确。问题是:它在邮差中正常工作

以下是来自服务器的响应标头(请注意,允许任何访问源):

404

以下是从React JS应用程序(收到404错误的应用程序)发出的请求的请求标头:

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

在Postman中,我设置了完全相同的请求标头,并向服务器发出完全相同的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 请求。它工作正常!我收到了空的200回复​​。

为了确保,我仔细检查了Apache访问日志。果然:

OPTIONS

请求方法完全相同,请求URL完全相同,除了一个返回200,另一个返回404,没有可辨别的原因。

此外,我应该将另一个 ... ::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 ... 请求添加到POST方法,工作得很好。

导致这种情况的原因是什么?

擅自解决方案

1。我看到了这个问题(React Native + fetch + API : DELETE request fails in App, works in Postman),即使我正在运行Apache而不是Nginx,我还以为我会尝试在请求网址中添加一个尾部斜杠。 create请求现在返回301错误(永久移动)。

2. 我删除了斜线并继续尝试修复。根据评论建议,我删除了自动路由生成并创建了自己的路径:

OPTIONS

Postman请求仍然返回200 OK,并且React请求仍然返回404 Not Found。

3。 Eureka!有点儿。根据另一条评论建议,我将Chrome中的请求作为cURL导出并直接导入Postman - 也许我在复制标题时遗漏了一些内容。我似乎做了,因为现在邮递员请求返回404!

在尝试禁用和/或启用导入的标头后,我确定问题是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'); Origin标头的组合。如果只有一个,则请求返回200,但如果两个都存在,我会收到404.

然而,这仍然让我不知道如何解决问题。在这一点上,我想知道这个问题是否可能更像是一个Laravel问题 - IE,为什么对完全有效的资源路由的Access-Control-Request-Method请求将返回404.我假设因为这些资源路由正在监听OPTIONSPUT但不是PATCH

1 个答案:

答案 0 :(得分:0)

由于已经设置了CORS,接下来要做的就是处理“预检” OPTIONS请求。您可以使用中间件来做到这一点:

PreflightRequestMiddleware

if ($request->getMethod() === $request::METHOD_OPTIONS) {
    return response()->json([],204);
}

return $next($request);

在新创建的中间件的handle()方法中添加以上代码。将中间件添加到全局中间件堆栈中。

此外,请不要忘记在CORS设置中将OPTIONS方法添加到Access-Control-Allow-Methods

有关更多选项,请检查this

答案:

阅读this文章。当浏览器向您的应用程序发送OPTIONS请求时,该应用程序无法处理该请求,因为您仅为给定端点定义了GET / POST / DELETE / PUT / PATCH路由。

因此,为了使该路线能够处理预检请求:

Route::get('/users', 'UserController@index');

它需要一条相应的OPTIONS路线:

Route::options('/users', 'UserController@options');

注意:您将使用中间件在一个地方处理所有OPTIONS请求。但是,如果您将OPTIONS请求用于其他目的-请查看此答案中的第一个链接以获取更多选项。