aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
15k stars 2k forks source link

There is no way to 'del_route' #752

Closed realcr closed 8 years ago

realcr commented 8 years ago

I sometimes want to remove a route from my web app, but it seems like there is no way to do this from the current app.router interface (UrlDispatcher in web_urldispatcher.py)

For example, I might do something like:

    app = web.Application(loop=loop)
    app.router.add_route('GET', '/my_route', handle)

And then later in my program remove this route, like this:

    app.router.del_route('GET', '/my_route', handle)

Is there a way to do this, or is this some kind of bad form and I should find another solution? Thank you for your help, and also thank you for this great library :)

asvetlov commented 8 years ago

Please provide your use case for route deletion. From my point of view route table should be configured before starting application and never changed in run-time.

realcr commented 8 years ago

I thought about it again and you are probably right. I wanted to write code that detaches from the app when the server closes, but most likely there is no reason to do that, as I am going to close my program anyways.

Thank you for the quick response :)

espositofulvio commented 6 years ago

I know this was closed a long time ago, but I have actually a use case where adding/removing routes and subapps can be useful. In particular, having the ability to add/remove routes/subapps can be an easy implementation for premium/paid features on a website. Imagine you have a basic service free to use, but like many portals you provide more or improved functionalities under payment/subscription. The additional/enhanced features might well be complete subapp or particular routes added or removed when the payment is done. Would you consider re-opening it or maybe a pull request if I have time to work on this?

kxepal commented 6 years ago

@espositofulvio That sounds like work for auth middleware.

The more realistic case is dynamic runtime web app configuration based on microservices-driven environment. But this case would require more advanced than UrlDispatcher router, which could implement required interface.

espositofulvio commented 6 years ago

@kxepal I thought about that, but I'd rather add and remove features completely instead of relying on an authorization mechanism. It also means less work, leaner websites, less surface for errors. This way I could also concoct a way to add features at runtime without server restarting, by means of an interface panel that can scan a directory for new packages which can dynamically add themselves to the application. Anyway, I guess that's something out of scope for aiohttp if there's no much interest in it.

asvetlov commented 6 years ago

I suggest making a subapp with custom router.

gdude2002 commented 6 years ago

Is there no chance of this being added to aiohttp at all?

I have a use-case for this; I'm writing a dynamically-configurable CMS with a plugin system, restarting the entire node isn't really a nice way to remove a set of routes when a plugin is unloaded, so it would be nice if aiohttp could support this out of the box.

I've been attempting to remove routes from the router myself, but coming up with unique identifiers (and later retrieving them after aiohttp does its magic) is proving tricky.

asvetlov commented 6 years ago

It's really complex problem. URL resolving is organized as following:

  1. Find a resource for given URL path
  2. Find a route inside the resource for handling corresponding HTTP method

Deletion should do the reverse with dropping resource if it handles no routes anymore.

How Django, Flask or other Python HTTP framework handles it? I don't recall such functionality.

gdude2002 commented 6 years ago

Most frameworks don't seem to handle it unfortunately. Nobody appears to know why, though.

The method I'm currently using is unique to my own application, since I have my own route registration system (so that we know what plugins own what routes), so I'm using the module/class name as a unique identifier and searching the router for routes with that identifier. It's working for now, I just feel like it's a poor way to do it.

espositofulvio commented 6 years ago

I don't think any of those frameworks do something similar but it could be really interesting when add_domain (or addsubdomain) will be added to aiohttp (and I hope the relative remove[sub]domain] too), multi-site and multi-tenancy systems would be very easy to implement.

asvetlov commented 6 years ago

In my mind route table should be frozen before starting serving the application, otherwise it opens a can of worms. Your feature request looks simple on surface but raises many complicated questions when digging into implementation. Maybe you need a custom resolver?

gdude2002 commented 6 years ago

In a sense, I can definitely see why one would want that. That said, it's just really not something you can do with a microkernel architecture, especially not if you want it to be configured on the fly.

I don't see any particular harm in adding the feature with a documented warning though, if you really feel like it'll mess people up.

asvetlov commented 6 years ago

Well, you can try to make a Pull Request with proposed implementation as subject for concrete discussion.

lock[bot] commented 4 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. If you feel like there's important points made in this discussion, please include those exceprts into that new issue.