12

There is a problem occurring while using APIs with trailing slash.

Route

Route::post('user/register','UserController@register');

It's working fine when I called this route POST from the postman/website, but I called this route from mobile with a trailing slash like the following.

user/register/

Laravel, by default, remove the trailing slash but make the request as GET when I dump the request method.

$method = $_SERVER['REQUEST_METHOD'];
$json = json_encode(['response' => $method], true);

result  -> "{response : 'GET'}"

And I am unable to fetch the request body.

NOTE: I have tried many solutions but couldn't find any solution, and also, I can't remove or update route calling from the mobile end, so I have to handle it on the server-side.

Karl Hill
  • 12,937
  • 5
  • 58
  • 95
Muhammad Shareyar
  • 772
  • 2
  • 7
  • 21

3 Answers3

6

When Laravel detects a trailing slash, it returns a 301 redirect to an "untrailed slash" version. The redirected request is always 'GET', so you won't be able to get the POST result.

The only way to prevent this (assuming you're using Apache) is go to your .htaccess file (should be in the public directory of your laravel installation) and remove the following:

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]

Now the URLs with trailing slashes won't be redirected anymore.

EDIT: If you want to prevent redirects of only certain URIs, instead of removing those lines, you need to specify a stricter condition. For example, to stop redirecting only the links containing "customer", you'll do this:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !customer
RewriteRule ^ %1 [L,R=301]

and only the links not containing "customer" anywhere will be redirected.

José A. Zapata
  • 1,187
  • 1
  • 6
  • 12
  • Can I check this for a specific route prefix? like if the route has `customer/` and then `user/register` then don't check the trailing slash else work as it is. – Muhammad Shareyar Aug 19 '21 at 14:40
0

As you said this is a api route, you should call it like:

api/user/register

if you cant change it from mobile, you should remove default api prefix from api routes in this way:

In app\Providers\RouteServiceProvider change Route::prefix('api') to Route::prefix('').

Abolfazl Mohajeri
  • 1,734
  • 2
  • 14
  • 26
0

Can you post your route file? There could be a small mistake in them. I tried it with a really simple code, and everything works as expected:

// routes/api.php
<?php

Route::post('/foo', function(Request $request) {
    return new JsonResponse('post');
});

Route::get('/foo', function(Request $request) {
    return new JsonResponse('get');
});

If I call the GET API with Postman with or without a trailing slash "get" is returned. If I call the POST API with Postman with or without a trailing slash "post" is returned.

The issue could also be from your mobile app not being configured properly rather than an issue in Laravel.

  • They are sending data with `xxx-www-urlencoded-form` so when they call the api with trailing slash `/` laravel by default removes the trailing slash and the method action I received is get as with an empty body. – Muhammad Shareyar Aug 23 '21 at 14:25