question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Routes with trailing slash do not work under default API Options

See original GitHub issue

Hello,

It seems when using the current default for api.req_options.strip_url_path_trailing_slash which is False, adding a slash at the end of a route doesn’t work.

I think I found out what the problem is.

Here is the code I tried:

import falcon

class StaticResource(object):

    def on_get(self, _: falcon.Request, resp: falcon.Response) -> None:
        resp.status = falcon.HTTP_200
        resp.content_type = 'text/plain'
        resp.body = 'static'

def create_app() -> falcon.API:
    api = falcon.API()
    api.req_options.strip_url_path_trailing_slash = False
    api.add_route('/static_route/', StaticResource())
    api.add_route('/static_route2', StaticResource())
    print(api._router._finder_src)
    return api

The finder_src compiled function is :

def find(path, return_values, patterns, converters, params):
    path_len = len(path)
    if path_len > 0:
        if path[0] == 'static_route':
            if path_len == 1:
                return return_values[0]
            return None
        if path[0] == 'static_route2':
            if path_len == 1:
                return return_values[1]
            return None
        return None
    return None

We see that the code generated for both routes is the same. The path passed to this function when calling uri: “http://127.0.0.1:8000/static_route/” is : [‘static_route’, ‘’] which has a length of 2, leading the function to return None and therefore an HTTPError 404. When calling uri: “http://127.0.0.1:8000/static_route”, the function returns the correct route and leads to HTTP 200.

Therefore using the default option leads to an impossibility to have routes ending with a trailing slash and even worse, when using routes ending with a trailing slash, the route without it works…

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
vishalrpcommented, Aug 9, 2019

Hello, we experienced this issue as well. We were on version 1.4.1 and one of the routes was defined with a / in the end. It used to work with and without the slash when queried. However, after upgrading, querying with a / returns a 404.

2reactions
nZaccommented, May 20, 2019

Hi @laurent-chriqui, thanks for submitting a bug report, we really appreciate when it includes code!

I am not sure I understand what you expect. Note that, req_options.strip_url_path_trailing_slash controls how the Request segments are determined, not how routing works, they are independent ideas.

Consider a route add_route('/home/', HomeResc()) and add_route('/home/{param}, Dashboard()).

How would you route a request to /home/data vs /home/ with strip_url_path_trailing_slash=False? Should /home/ go to HomeResc or should it go Dashboard? I think there is an argument it should go to Dashboard with param="" and that is what it does. Here is a quick example:

import falcon
import falcon.testing
import falcon.routing


class TestResource:
    def on_get(self, req, resp, **kwargs):
        resp.media = {'params': kwargs}


api = falcon.API()
api.add_route('/home/', TestResource())
api.add_route('/home/{id}', TestResource())

client = falcon.testing.TestClient(api)

api.req_options.strip_url_path_trailing_slash = False
assert client.simulate_get('/home').json['params'] == {}
assert client.simulate_get('/home/').json['params'] == {'id': ''}
assert client.simulate_get('/home/data').json['params'] == {'id': 'data'}

This changes slightly with strip_url_path_trailing_slash=True:

# ... same as above

api.req_options.strip_url_path_trailing_slash = True
assert client.simulate_get('/home').json['params'] == {}
assert client.simulate_get('/home/').json['params'] == {}.  # Note, we don't get `id`
assert client.simulate_get('/home/data').json['params'] == {'id': 'data'}

This might point to us needing to raise when there is a trailing slash passed to add_route since it is ultimately meaningless.

Morale of the story strip_url_path_trailing_slash is about the Request handling not about the routers behavior.

I am going to mark this as needing documentation here. If the other maintainers think there are code level changes for this… or if I am patently wrong (that happens far more often than I like!) please let me know!

Bonus… if you would like it to be different you can change it! 🎉

Bonus 2… If you are actually trying to serve statics, you might want to look at add_static_route. If it doesn’t meet your needs, let us know, we might be able to add features!

Bonus 3… Thanks again for submitting this!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Route is not triggered with trailing slash in web api 2
I just tested my own web api and a trailing slash does not affect the routing. This is for routes created with attributes,...
Read more >
Should You Have a Trailing Slash at the End of URLs? - Ahrefs
A trailing slash is a forward slash (“/”) placed at the end of a URL such as domain.com/ or domain.com/page/. But should you...
Read more >
Routing in Razor Pages
Routing is the system that matches URLs to Razor pages. Like most page-centric frameworks, the primary routing system in ASP.
Read more >
Routing (Symfony Docs)
Routes can be configured in YAML, XML, PHP or using attributes. ... The query string of a URL is not considered when matching...
Read more >
Configure Hosting behavior | Firebase Hosting - Google
The default value is a directory named public , but you can specify any directory's path, as long as it exists in your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found