Laravel 8: POST request is treated as GET

Viewed 111

I have two routes which accept optional parameters:

Route::get('application/cedula/{cedula}/{view?}/{model?}', 'App\Http\Controllers\ApplicationController@getCedulaInformationFromPublicServices')->name('application.cedula');
Route::post('application/cedula/{cedula}/verification/{code?}', 'App\Http\Controllers\ApplicationController@verifyApplicationCode')->name('application.confirm');

public function verifyApplicationCode( Request $request, String $cedula, String $code = NULL ) {...}
public function getCedulaInformationFromPublicServices( String $cedula, String $view = NULL, String $model = NULL){...}

When I make a POST request to application/cedula/0001001010/verification, without the optional parameter "{code?}", it enters to the GET route.

I know that it's passing "verification" to the GET endpoint as the optional parameter {view?}, but shouldn't the resquest type be enough to discern between which one to follow despite the endpoint names being similar.

2 Answers

"shouldn't the resquest type be enough to discern between which one to follow despite the endpoint names being similar"? Yes, it's enough. The problem is not about your code. Even I it was like:

Route::get('application/cedula/{cedula}/{view?}/{model?}', 'App\Http\Controllers\ApplicationController@getCedulaInformationFromPublicServices')->name('application.cedula');
Route::post('application/cedula/{cedula}/{view?}/{model?}', 'App\Http\Controllers\ApplicationController@verifyApplicationCode')->name('application.confirm');

there couldn't be a problem. There would be a problem when there exists more than one potential match like this:

Route::post('application/cedula/{cedula}/{view?}/{model?}', ...);
Route::post('application/cedula/{cedula}/verification/{code?}', ...);

Now if you make a POST request to application/cedula/0001001010/verification/model1, the first route comes first so it would be selected. That's because when accessing a route, Laravel goes through your routes top to bottom, until it finds the first match, at which point this route is immediately selected.

But in your case there wouldn't be a problem because your routes are of different request types. Try using php artisan route:list to check whether they are cached. If not, the problem is the way you are testing them. I'd recommend something like Postman.

Try to re-arrange your route, putting the routes with constant path first

Route::post('application/cedula/{cedula}/verification/{code?}', 'App\Http\Controllers\ApplicationController@verifyApplicationCode')->name('application.confirm');
Route::get('application/cedula/{cedula}/{view?}/{model?}', 'App\Http\Controllers\ApplicationController@getCedulaInformationFromPublicServices')->name('application.cedula');

Do not forget to run: php artisan route:clear

Related