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

Adding optional trailing_slash for SimpleRouter and test #9659

Closed
wants to merge 4 commits into from

Conversation

decadenza
Copy link
Contributor

Description

For someone it is annoying to have to choose specifically if an API has to have or not the trailing slash. So I added a way to have an optional trailing slash.

This does not break the previous behaviour, where trailing_slash can be only True or False. By default it stays True as before.

There is not an extra option: when trailing_slash=None (or any other value), the trailing_slash becomes optional.
For clarity, we may use something else than None.

Test has been added.

decadenza and others added 4 commits January 30, 2025 09:47
This does not break the previous behaviour, where trailing_slash can be only True or False. By default it stays True.
It adds an extra option: when trailing_slash=None (or any other value), the trailing_slash becomes optional.
@decadenza
Copy link
Contributor Author

This is alternative to use a custom class like:

from rest_framework.routers import SimpleRouter

class ExtendedSimpleRouter(SimpleRouter):
    """
    Extends the simple router to add minimum configuration options,
    like optional trailing slash.
    """
    def __init__(self, *args, **kwargs):
        super(ExtendedSimpleRouter, self).__init__()
        self.trailing_slash = "/?"

in our code.

@decadenza
Copy link
Contributor Author

For clarity, especially in documentation, one may also use:
SimpleRouter(trailing_slash="optional")
with the same effect of None, as the optional trailing slash will be added every time the argument is neither True or False.

@sevdog
Copy link
Contributor

sevdog commented Feb 28, 2025

Why having an optional trailing slash (in the regex) and not using the APPEND_SLASH config?

@decadenza
Copy link
Contributor Author

Hi @sevdog and thank you for replying.

I have an embedded device that sends a POST request to myserver.com/api/endpoint with and without trailing slash.
From the APPEND_SLASH configurations, I quote:

Note that the redirect may cause any data submitted in a POST request to be lost.

So losing the data is the first concern.

Secondly, it is more efficient than having Django constantly performing internal redirects (apart for losing data). The difference in the regex evaluation runtime should be negligible.

See also https://stackoverflow.com/a/46163870/3396785

Any thoughts?

@sevdog
Copy link
Contributor

sevdog commented Feb 28, 2025

An other concern is that with this kind of implementation if you have use_regex_path=False it is going to cause problems to other URLs.

You could also achieve the same result by using two routers: one with trailing_slash=True and one with trailing_slash=False.

@sevdog
Copy link
Contributor

sevdog commented Feb 28, 2025

An other way to obtain this is to override CommonMiddleware to provide a redirection using HTTP status 308 which tells the client to keep method and body.

@decadenza
Copy link
Contributor Author

decadenza commented Feb 28, 2025

I did not consider the use_regex_path=False situation, but it may be taken into account simply by doing:

if trailing_slash is True:
    self.trailing_slash = '/'
elif trailing_slash is False:
    self.trailing_slash = ''
else:
    if use_regex_path is False:
        self.trailing_slash = "/"         # No regex, no party... Use the trailing slash as default.          
    else:
        self.trailing_slash = "/?"        # Optional trailing slash as before.

Using two routers does not seem DRY.

Not sure about the middleware solution. I think that's more of a Django PR than of this framework.

How would you address this optional trailing slash thing in one of your projects?

@sevdog
Copy link
Contributor

sevdog commented Mar 3, 2025

I have an embedded device that sends a POST request to myserver.com/api/endpoint with and without trailing slash.

How would you address this optional trailing slash thing in one of your projects?

This seems to be an issue with the embedded device to me, because /endpoint and /endpoint/ are two dirrefent URIs and the client should be aware of this. If the same device (software) sometimes adds/removes the trailing slash this is a bug in that software.

See also https://stackoverflow.com/q/61547014

This said, this PR is not going to be merged because of current contributing policy because there are ways to make everything work without any change in DRF and this is not a feature of Django.

@tomchristie tomchristie closed this Mar 3, 2025
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

Successfully merging this pull request may close these issues.

3 participants