Skip to content

Trailing slash in URL for POST method causes error #654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
michael-erwin opened this issue Sep 20, 2017 · 9 comments
Closed

Trailing slash in URL for POST method causes error #654

michael-erwin opened this issue Sep 20, 2017 · 9 comments

Comments

@michael-erwin
Copy link

  • Lumen Version: 5.5.0
  • PHP Version: 7.1.1
  • Database Driver & Version: MariaDB 10.1.21

Description:

When sending POST request to URL with additional slash added at end the response results to "405 Method Not Allowed".

Steps To Reproduce:

  1. Make a route for POST.
    Example:
$router->post('/test', function () {
    return "POST request detected.";
});
  1. Send a POST request to the route with additional slash at the end.
    Example:
http://api.blog.local/v1/test/
@hakuno
Copy link

hakuno commented Oct 25, 2017

Read the HTTP specs, the correct is:

http://api.blog.local/v1/test

@michael-erwin
Copy link
Author

I don't think so. HTTP specs has nothing to do with it. It's more on how you would interpret a RESTful resource. Have a look

REST for Web Services

Trailing slash only means "collection".

POST http://api.blog.local/posts/ -> means create an element(s) to a collection

I mentioned POST specifically because the rest of the verbs works as expected.

@humbertowoody
Copy link

I'm currently experiencing the same issue. The weird thing about this is that the trailing / is actually non-problematic on previous versions of Laravel, maybe it's some issue on 5.5+. Actually what @michael-erwin is pointing out is true since some browsers add trailing characters and it shouldn't affect endpoints on an API or some other Web Services. Ultimately, a rewrite directive on the Apache/Nginx configuration should do the trick (or not?).

@snuggs
Copy link

snuggs commented Mar 16, 2018

@michael-erwin REST has nothing to do with this as well. from a URI perspective a trailing slash to a collection is about as relevant as a path to a bonafied file. COULD be but not necessarily (nor is this defined). I feel a little tangental however your concern is valid. Just stumbled across this when researching the very same topic in another ecosystem.I know the specs like the back of my hand but Laravel not so much. Assuming Ockham's Razor in effect i'd assume any route to /test to only be able to route to /test unless explicitly stated not to. From the canonical URL spec /foo and /foo/ are two totally different resources. A redirection which is commonplace is merely a convention that developed from the web. Google would also treat these as different endpoints as well depending on canonical strategies (e.g. 301 status code or <link rel=canonical>)

some browsers add trailing characters and it shouldn't affect endpoints on an API or some other Web Services. @humbertowoody

This is news to me. Can you provide examples? I work with all the vendors on a daily basis implementing specs. Never heard of this. Is actually bug worthy in the respective browser if this is true as there is nothing within the specs that mandates this. I wouldn't count on this bug/feature to be future proof. I don't ever promise anything and I can promise you that one.

...it shouldn't affect endpoints on an API or some other Web Services.

That's a vast assumption. The Facts are the spec, SEO, etc. encourage otherwise. However framework implementors keep perpetuating anti-patterns. It winds up in our laps as "just how we were taught". Just because the framework behaves this way doesn't mean it's correct. Over in WHATWG i'm dealing with the fact the world used text/javascript as a mimetype although applicaiton/javascript may be better suited. Too late for this now. anti-pattern already become habit. I do know that many routing systems give the ability to capture slash/no-slash. Some use the "Same resource for both routes" strategy which is bad for the web. Other frameworks make things very painful for developers when they start assuming things for the developer especially regarding URLS. Just ask Angular & Django that mutually excluded each other. While others use 301 redirection strategy. Which is perfectly standard and makes the web happy.

To make a long story longer, as stated before /foo & /foo/` are two totally different resources and a trailing slash may have conventions around it but shouldn't convey much. Frameworks definitely shouldn't do much assuming for the developer here. Or even worse make a breaking change as @humbertowoody mentioned earlier.

capture d ecran 2018-03-15 a 23 09 15

@snuggs
Copy link

snuggs commented Mar 16, 2018

After speaking with some spec members @humbertowoody the browser adds a / for root domain addresses. anything else typically they shouldn't. example.com would need some path to send to the server in the HTTP request. GET / this is where the example.com/ comes from. GET /foo is totally valid path so the server would receive /foo not /foo/

Does this make sense?

@driesvints
Copy link
Member

This works for me. Try updating to the latest version.

@ramsesmoreno
Copy link

It may be also something related to the web server, because in my case, it works both ways locally and the same script sends an error on production if called with a trailing slash.

@Arthur-Kamau
Copy link

Is there i way i could fix this issue in the server,
as the application has already been pushed into production

@aduuna
Copy link

aduuna commented Jul 25, 2019

In web.php

Route::post('/comments', 'CommentController@store')

In views/comments/create.blade.php

<form action="/comments/" method="POST">
...

This works fine when serving locally with $ php artisan serve in version 5.8.28 (latest)

But fails in production with Apache or NGINX server

My Advice

Instead of hard-coding the resources, You should use resource/route names. In that case, you never have to remember if your server will trim/append a trailing slash.

In web.php

Route::post('/comments', 'CommentController@store')->name('comments.store')

In views/comments/create.blade.php
<form action="{{ route('comments.store') }}" method="POST">

Read more on url generation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants