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

router.add_static is greedy #5250

Closed
redsquirrel opened this issue Nov 16, 2020 · 5 comments · Fixed by #5534
Closed

router.add_static is greedy #5250

redsquirrel opened this issue Nov 16, 2020 · 5 comments · Fixed by #5534
Labels

Comments

@redsquirrel
Copy link

redsquirrel commented Nov 16, 2020

🐞 Describe the bug

The first argument for add_static matches on any path that starts with that string. For instance, if you specify "h", then add_static will match on "h" or "help" or "hoover".

💡 To Reproduce

Run this code:

from aiohttp import web

async def handle(request):
    name = request.match_info.get('name', "Anonymous")
    text = "Hello, " + name
    return web.Response(text=text)

app = web.Application()

router = app.router

router.add_static("/h", "./")

router.add_routes([web.get('/', handle),
                web.get('/{name}', handle)])

if __name__ == '__main__':
    web.run_app(app)

Add a text file in the current working directory named test.txt and put some text in there.

Then navigate to the following URLs to demonstrate the issue:

The last link unexpectedly returns a 404.

💡 Expected behavior

I would have expected http://0.0.0.0:8080/hoover to have similar behavior to http://0.0.0.0:8080/groot, and render "Hello, hoover".

📋 Your version of the Python

3.8

📋 Your version of the aiohttp/yarl/multidict distributions

aiohttp 3.7.2

@asvetlov
Copy link
Member

The order of routes is important, the search is stopped on the first match.
Is the static route more ready than the plain or dynamic one?

@redsquirrel
Copy link
Author

redsquirrel commented Nov 17, 2020

@asvetlov I'm not sure what you mean by "more ready".

@alex-eri
Copy link
Contributor

router.add_static("/h/", "./")

@redsquirrel
Copy link
Author

@alex-eri That has no effect due to this logic where any trailing slash is removed: https://github.com/aio-libs/aiohttp/blob/master/aiohttp/web_urldispatcher.py#L1097

@danking
Copy link
Contributor

danking commented Mar 10, 2021

I also encountered this. It's rather surprising that router.add_static("/tutorials/", ...) would match /tutorials-landing.html.

It seems like the fix should be in StaticResource.resolve:

    async def resolve(self, request: Request) -> _Resolve:
        path = request.rel_url.raw_path
        method = request.method
        allowed_methods = set(self._routes)
        if not path.startswith(self._prefix + "/"):
            return None, set()
        # ....

That seems safe and correct considering that the resolved filename implicitly assumes that the character following the prefix is irrelevant:

        match_dict = {"filename": _unquote_path(path[len(self._prefix) + 1 :])}

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

Successfully merging a pull request may close this issue.

4 participants