-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Middleware for Blueprint.group() #1386
Comments
@chenjr0719 @ahopkins @sjsadowski Let me take a stab at this? |
@harshanarayana Yes please go get a try. Actually, I have no idea how to implement this feature.:sweat_smile: |
This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue sanic-org#1386 Signed-off-by: Harsha Narayana <[email protected]>
@chenjr0719 @ahopkins @sjsadowski I just created a new PR #1399 for the same. |
@harshanarayana Thanks! I will take a look. @vltr has been working on So, if you want to use it now, maybe give that a try. I am marking this as a Future Release as I do not see this as a feature we want to add for 18.12. We are trying to keep the upcoming December (and first) LTS release with a limited amount of "new" features. I will let @sjsadowski and @yunstanford decide if they want to add that to 19.03 or not. |
@ahopkins That sounds good. Since this modifies the existing behavior of the Thanks for pointing me in the direction of |
@harshanarayana as @ahopkins mentioned, I had my time working on a solution for this. Since I wanted a more performant router for my Sanic applications, I chose to add "route specific" middlewares inside the routing tree (I created a project called xrtr for that, based on a Radix Tree). Basically (in You can check this working here. Unfortunatelly, I also wanted the flexibility to add a middleware for a certain route under a certain method, ex. a middleware that would only execute on |
@harshanarayana oh, and I found your solution quite interesting, but had no time to test it yet. I hope I find some soon 😉 |
@vltr I saw your benchmark script a few days ago and I've to say its super handy and useful. I've been going over the implementation in |
@vltr I've been wondering of a few more middleware cases other than the one you mentioned above, I was wondering how you feel about these middleware behaviors.
|
Intention behind the current implementation if provide a possible future enhancement where we can bring in the following to Blueprint Group Level. This can come handly when you don't want to add boiler plate code just to register listener/any other such items to each blueprints individually. Hope that makes sense
|
I am also of the opinion that a more prrformant router and modular Middleware are features we should add to sanic core. My initial reaction to the conditional Middleware idea was that it might add overhead to achieve, and I'm not sure it couldn't add anything that wouldn't be solved with blueprint Middleware and an if statement. |
bp1 = Blueprint('bp1', url_prefix='/bp1')
bp2 = Blueprint('bp2', url_prefix='/bp2')
@bp1.route("/somepath/<some_param>")
def somepath_bp1(request, some_param):
return text("OK")
@bp1.route("/something/<some_param>")
def something_bp1(request, some_param):
return text("OK")
@bp2.route("/somepath/<some_param>")
def somepath_bp2(request, some_param):
return text("OK")
@bp2.route("/something/<some_param>")
def something_bp2(request, some_param):
return text("OK")
group = Blueprint.group(bp1, bp2, url_prefix="/api")
@group.middleware('request', condition={
'route': {
'pattern': r'.*something.*',
'check': 'match'
}
})
def conditional_group_middleware(request):
# do something Let's take the above example, I want the Middleware to be applied to both Blueprints but only for those routes that match the regex criteria This reason I was thinking this is, I don't want my request to go into some of the middleware at all if it's not essential. I would rather wait for an extra second during the bootup rather wait during the response. Wouldn't you agree? |
For number 1, I totally agree and would love to see that! As for 2, if we can apply Middleware at the blueprint level (in addition to app and blueprint group), wouldn't that essentially do the same thing? If the condition is a function of the route, then it seems this could be achieved with nesting of blueprints. ESPECIALLY, if there was the ability in number one for customizing the router or providing a drop in replacement. |
But yes, I agree... it's a web server. Bootup time is not so important. I was thinking you were talking about request level conditions. |
Yeap, I want to add some other routers in there in the future, but only Python ones (or ones that provide a Python interface at least).
Thanks! I have a slightly different approach with sanic-boom than I have with Sanic (like not having any static file utilities; in my opinion it's useless), but component injection and all that neat stuff would be great to incorporate into Sanic itself, but I don't know if this would go on because it has a performance penalty on each request ... There's always C and Cython to the rescue, but this may add another layer of complexity to the code. This need a broader discussion with the core developers and the whole community to be honest.
Like @app.route("/auth", param={"t": match_ignorecase("jwt")})
async def myjwtfunc(...):
# code here
@app.route("/auth", param={"t": match_ignorecase("saml")})
async def mysamlfunc(...):
# code here I have thought on that. This also can be used to implement header based conditions to the router as well: @app.route("/api", header={"content-type": match_ignorecase("application/json")})
async def myjson(...):
# code here
@app.route("/api", header={"content-type": match_ignorecase("application/xml")})
async def myxml(...):
# code here
This already exists in Sanic, doesn't it?
Not with vanilla Sanic, only in sanic-boom I implemented this feature (you can use any parameters you want as long as they match some
Yeap, the Sanic router does it job with some possible pitfalls here and there but it doesn't scale well if the LRU cache is not used very often; as well being very complex. I'm rewriting xrtr to be in pure C with Python bindings, allowing the usage of regex (using |
@vltr I'll be glad to lend you a hand with any enhancement to the benchmarking script if and where there is a need for it.
I personally like the idea of having a static file utility handy just if I need it. it doesn't have to be over the top fancy, but if it can do the bare minimum that is more than sufficient.
Exactly my thought. It might look like some kinda trickery when you read the code and try to figure out how the flow even gets there, but from an end user implementation standpoint, I can have distinctive methods defined that can do one single thing it's supposed to do. Easy to test and easy to manage. (PS, I am not a big fan of methods having @app.route('/secure')
def secure_method(request):
# do something 007 would do.
@app.middleware('request', header={'X-Auth-Mode': match_ignorecase('jwt')}
def auth_with_jwt(request):
# use sanic-jwt and wish, let there be light.
@app.middleware('request', header={'X-Auth-Mode': match_ignorecase('saml')}
def auth_with_saml(request):
# Please go back to using JWT 🗡 or authenticate yourself. The above example just tells you what I had in mind. Almost similar to what you mentioned but with a minor tweak. This can be applied at the Blueprint, Blueprint Group or at all level and you will have an easy way to control middleware invocation. But, like @ahopkins mentioned, PERFORMANCE overhead!
Yes it does. I did some basic testing to ensure it works the way I expected and it does. Any middleware attached to These things can come extremely handly when you are implementing a rate-limiting behavior on the API as well as exporting some API metrics to a destination of your choosing. Not to forget response caching behaviors that can be put into the system as a plugin.
Oh Okay. I don't know if it's just me or not, but I would love to see this feature made available in vanilla The other way is to implement the
This sounds like a great idea. Looking forward to seeing how that works. |
This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue sanic-org#1386 Signed-off-by: Harsha Narayana <[email protected]>
This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue sanic-org#1386 Signed-off-by: Harsha Narayana <[email protected]>
This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue sanic-org#1386 Signed-off-by: Harsha Narayana <[email protected]>
This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue sanic-org#1386 Signed-off-by: Harsha Narayana <[email protected]>
* enable blueprint group middleware support This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue #1386 Signed-off-by: Harsha Narayana <[email protected]> * enable indexing of BlueprintGroup object Signed-off-by: Harsha Narayana <[email protected]> * rename blueprint group file to fix spelling error Signed-off-by: Harsha Narayana <[email protected]> * add documentation and additional unit tests Signed-off-by: Harsha Narayana <[email protected]> * cleanup and optimize headers in unit test file Signed-off-by: Harsha Narayana <[email protected]> * fix Bluprint Group iteratable method Signed-off-by: Harsha Narayana <[email protected]> * add additional unit test to check StopIteration condition Signed-off-by: Harsha Narayana <[email protected]> * cleanup iter protocol implemenation for blueprint group and add slots Signed-off-by: Harsha Narayana <[email protected]> * fix blueprint group middleware invocation identification Signed-off-by: Harsha Narayana <[email protected]> * feat: enable list behavior on blueprint group object and use append instead of properly to add blueprint to group Signed-off-by: Harsha Narayana <[email protected]>
I think this can now be closed in favor of merged PR #1399 |
* enable blueprint group middleware support This commit will enable the users to implement a middleware at the blueprint group level whereby enforcing the middleware automatically to each of the available Blueprints that are part of the group. This will eanble a simple way in which a certain set of common features and criteria can be enforced on a Blueprint group. i.e. authentication and authorization This commit will address the feature request raised as part of Issue sanic-org#1386 Signed-off-by: Harsha Narayana <[email protected]> * enable indexing of BlueprintGroup object Signed-off-by: Harsha Narayana <[email protected]> * rename blueprint group file to fix spelling error Signed-off-by: Harsha Narayana <[email protected]> * add documentation and additional unit tests Signed-off-by: Harsha Narayana <[email protected]> * cleanup and optimize headers in unit test file Signed-off-by: Harsha Narayana <[email protected]> * fix Bluprint Group iteratable method Signed-off-by: Harsha Narayana <[email protected]> * add additional unit test to check StopIteration condition Signed-off-by: Harsha Narayana <[email protected]> * cleanup iter protocol implemenation for blueprint group and add slots Signed-off-by: Harsha Narayana <[email protected]> * fix blueprint group middleware invocation identification Signed-off-by: Harsha Narayana <[email protected]> * feat: enable list behavior on blueprint group object and use append instead of properly to add blueprint to group Signed-off-by: Harsha Narayana <[email protected]> add port to url_for, and update doc for it, reset scheme and external if server not specified in url_for add port to url_for, and update doc for it, reset scheme and external if server not specified in url_for Revert "add port to url_for, and update doc for it, reset scheme and external if server not specified in url_for" This reverts commit b073dfa.
Is your feature request related to a problem? Please describe.
Not related to any problem but about better usage of
Blueprint.group()
. I've to say that middleware ofBlueprint()
is a really useful feature. And I hope thatBlueprint.group()
can also support this useful feature.Describe the solution you'd like
For example, I have lots of blueprints and all of them are grouped by
Blueprint.group()
. In this case, if I want to apply a function(authorization for example) to all blueprints, I would like to just add middleware toBlueprint.group()
.Additional context
Here is an example:
Let me know your idea.
The text was updated successfully, but these errors were encountered: