Skip to content
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

Support endpoints with redirect from trailing slash to no trailing slash (and vice-versa) #756

Open
agboom opened this issue Feb 26, 2021 · 2 comments

Comments

@agboom
Copy link
Contributor

agboom commented Feb 26, 2021

Previously discussed here: https://gitter.im/endpoints4s/endpoints4s?at=6036b1b500454662095017c8

This ticket has become pretty long, partly because I'm learning about the subject while writing it. If you are familiar
with the no trailing slash or trailing slash issue in APIs, please skip or glance over the background part.

Background

An endpoint can have the URI /foo/ or /foo. Both are technically different URIs, so /foo/ (with a trailing slash)
points to a different resource than /foo [5]. The general consensus is that using both can cause confusions to users
of the API and mess up clients, crawlers and caches [1] [2].

An often used solution for APIs is to choose one format and redirect one to the other (e.g. redirect /foo/ to /foo) [3].
This guarantees that the content is served on one url and it is clear which is canonical, namely the resource that the
redirected resource points to.

Within the REST standard there's a different semantic for both URIs, /foo pointing to a single resource and /foo/ to
a resource group (although this is not definitive, as REST is a de-facto standard) [4].

For APIs that put relative URIs in their response pointing to some other resource, like an image, the trailing slash can
make the difference between a working app or a broken app [2]. I don't know how common this use case is, the linked article [2]
shows some applications.

Long story, but it shows that there's no one widely accepted standard for structuring API URIs, at least not with
respect to trailing slashes. In my experience applying one standard consistently over a broad set of endpoints (for
example in a microservice platform) can also be challenging.

Redirects in Endpoints4s

Endpoints4s has no algebra for redirects, so a redirect response must be done in the server implementation. This is
understandable, because redirects do not really add value in clients or OpenAPI documentation.

But in the case of the (no) trailing slash standards you'd probably want to apply one standard consistently, maybe over
one project, maybe over a set of projects or modules. Endpoints4s could help in this respect by providing default
implementations of these various conventions. Other server frameworks do this as well. For example, Akka HTTP has
redirectToNoTrailingSlashIfPresent and redirectToTrailingSlashIfMissing directives.

The interface of an endpoint is clean and concise, and for me a list of endpoint definitions reads like a clean spec
of my API. I think having a clean way to tell the endpoint you want to redirect /foo/ to /foo in the same definition
would be a valuable addition.

So my first question is: do you agree we should add this to Endpoints4s? I'm willing to do the implementation work,
though I might need some help with determining the interface and getting some pointers in the right direction.

Sources:

[1] https://developers.google.com/search/blog/2010/04/to-slash-or-not-to-slash
[2] https://cdivilly.wordpress.com/2014/03/11/why-trailing-slashes-on-uris-are-important/
[3] https://restfulapi.net/resource-naming/
[4] https://softwareengineering.stackexchange.com/questions/186959/trailing-slash-in-restful-api
[5] https://stackoverflow.com/questions/61547014/restful-uri-trailing-slash-or-no-trailing-slash

@julienrf
Copy link
Member

julienrf commented Jul 8, 2021

Is this fixed by #742?

@agboom
Copy link
Contributor Author

agboom commented Jul 8, 2021

No, but it lays part of the groundwork for fixing it. I'd like to take a stab at this when #794 is finished, because I think it would make things easier. Maybe I'll pick up this issue to test the proposed implementation there.

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

2 participants