comment Kernel.php / VerifyCsrfToken and test PUT DELETE POST again
[L5] MethodNotAllowedHttpException on a existing route.
I'm developping a public API since a couple of month under Laravel 5 and ran into a odd issue : All the methods PATCH, PUT and DELETE aren't working.
My local env : PHP 5.6 (also tried with 5.5), Nginx 1.6.2, and latest L5 commit (https://github.com/laravel/framework/commit/7e0a6472e7cfed16d3635b0da58d14f14a42c2a3).
I'm using Postman extention to test my API and set the requests like this :
POST /v1/feeds/ HTTP/1.1
Host: api.metanews.local
Cookie: laravel_session=eyJpdiI6Iit2M283bnQxcmRcL0F1TjNPa2g3OFwvQT09IiwidmFsdWUiOiJDbUQ0czJkTnV0OXBZNFQrNlN6S1Q4OGZKUlBWVERBRXE3MHhGa1ZDYUVWOG1VV1JMVUFGTEE0ZEpZR0tSOXk4UFl0b1lKZUlIME1RdWFmenBwRkdJQT09IiwibWFjIjoiNTVlYWQ3NjdhMTc4N2Y0MDE3YzY4Y2VkZDdjMmYzMGRhMzE4MDY2ODk3NjcxMWM3Zjg0NjAwOTk0Zjk1Mjc4YSJ9
X-Tenant-Key: stringexemple
Authorization: Basic stringbase64encoded
Cache-Control: no-cache
Postman-Token: fe87f096-09cd-d4c2-6e3d-eb6f1ccb7790
Content-Type: application/x-www-form-urlencoded
_method=PATCH
I also tried with curl, and had the same issue...
This kind of requests used to work. I didn't change my router.php since and nothing has change in the laravel's Router layer at my knowledge....
Routes are well-listed with the php artisan route:list (and I cleared any route cache just to be sure) but HTTP requests != (GET|POST) keeps failing.
My sample routes.php
<?php
$router->group(['prefix' => 'v1', 'namespace' => 'V1', 'middleware' => ['tenant', 'auth.basic', 'authorize']], function($router) {
$router->get('feeds/trashed', ['uses' => 'FeedsController@trashed', 'as' => 'v1.feeds.trashed']);
$router->patch('feeds/restore/{feeds}', ['uses' => 'FeedsController@restore', 'as' => 'v1.feeds.restore']);
$router->resource('feeds', 'FeedsController', [
'only' => ['index', 'show', 'store', 'update', 'destroy']
]);
});
php artisan route:list output
| Method | URI | Name | Action |
| ----------------- | ------------------------------------ | -------------------------- | -------------------------------------------------------------------------------------- |
| GET|HEAD | v1/feeds/trashed | v1.feeds.trashed | Metanews\Http\Controllers\V1\FeedsController@trashed |
| PATCH | v1/feeds/restore/{feeds} | v1.feeds.restore | Metanews\Http\Controllers\V1\FeedsController@restore |
| GET|HEAD | v1/feeds | v1.feeds.index | Metanews\Http\Controllers\V1\FeedsController@index |
| POST | v1/feeds | v1.feeds.store | Metanews\Http\Controllers\V1\FeedsController@store |
| GET|HEAD | v1/feeds/{feeds} | v1.feeds.show | Metanews\Http\Controllers\V1\FeedsController@show |
| PUT | v1/feeds/{feeds} | v1.feeds.update | Metanews\Http\Controllers\V1\FeedsController@update |
| PATCH | v1/feeds/{feeds} | v1.feeds.update | Metanews\Http\Controllers\V1\FeedsController@update |
| DELETE | v1/feeds/{feeds} | v1.feeds.destroy | Metanews\Http\Controllers\V1\FeedsController@destroy |
And debugger tells me :
MethodNotAllowedHttpException in RouteCollection.php line 207:
in RouteCollection.php line 207
at RouteCollection->methodNotAllowed(array('GET', 'HEAD', 'POST')) in RouteCollection.php line 194
at RouteCollection->getRouteForMethods(object(Request), array('GET', 'HEAD', 'POST')) in RouteCollection.php line 142
at RouteCollection->match(object(Request)) in Router.php line 702
at Router->findRoute(object(Request)) in Router.php line 628
at Router->dispatchToRoute(object(Request)) in Router.php line 604
at Router->dispatch(object(Request)) in Kernel.php line 155
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 141
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in ShareErrorsFromSession.php line 55
at ShareErrorsFromSession->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in StartSession.php line 53
at StartSession->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 36
at AddQueuedCookiesToResponse->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in EncryptCookies.php line 40
at EncryptCookies->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in CheckForMaintenanceMode.php line 42
at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 125
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 101
at Pipeline->then(object(Closure)) in Kernel.php line 108
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 83
at Kernel->handle(object(Request)) in index.php line 53
After some research, it seems that the check function in \Illuminate\Routing\RouteCollection has an odd behavior
<?php
/**
* Determine if a route in the array matches the request.
*
* @param array $routes
* @param \Illuminate\http\Request $request
* @param bool $includingMethod
* @return \Illuminate\Routing\Route|null
*/
protected function check(array $routes, $request, $includingMethod = true)
{
return array_first($routes, function($key, $value) use ($request, $includingMethod)
{
return $value->matches($request, $includingMethod);
});
}
The $value->matches returns true if a declared route is matched, and with some dd(), I discovered that it returns true at some point, but the check function returns null...
Please or to participate in this conversation.