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

Cannot define a blueprint-specific exception handler #2202

Closed
komar007 opened this issue Jul 22, 2021 · 5 comments · Fixed by #2208
Closed

Cannot define a blueprint-specific exception handler #2202

komar007 opened this issue Jul 22, 2021 · 5 comments · Fixed by #2208
Assignees

Comments

@komar007
Copy link

Describe the bug
The documentation at https://sanicframework.org/en/guide/best-practices/blueprints.html#exceptions says that:

Just like other exception handling, you can define blueprint specific handlers.

However, exception handlers defined this way don't seem to be blueprint-specific at all. Instead, they handle exceptions in other blueprints as well.

Code snippet

#!/usr/bin/env python3

from sanic import Sanic, Blueprint, response

class Error(Exception):
    pass

handled = Blueprint("handled")
@handled.exception(Error)
def handle_error(req, e):
    return response.text("handled {}".format(e))

b = Blueprint("b")
@b.route("/")
def e(request):
    raise Error("error in e")

app = Sanic(__name__)
app.blueprint(handled)
app.blueprint(b)
app.run()

Expected behavior
A request to http://localhost:8000 should generate 500, because Error should not be handled.
Instead, the request generates 200, Error is handled, even though the handler is registered in handled, while the endpoint is in b.

Environment (please complete the following information):

  • OS: ubuntu 19.10
  • Version: Sanic 21.6.0; Routing 0.7.0

Additional context
The order of blueprint registration does not seem to change anything. Not registering blueprint handled obviously fixes the issue.

Is it a bug or am I missing something here?

@ahopkins
Copy link
Member

ahopkins commented Aug 1, 2021

Sorry for not responding earlier. I am looking at this. See also #2121

@komar007
Copy link
Author

@ahopkins,
sorry for not responding too.

I have tried the latest master, but it seems the test above still fails - the exception is still caught:/
Could I be doing something wrong there?

@ahopkins
Copy link
Member

@komar007 Well, I think you found an interesting use case that is not accounted for.

In your use case above, the handled Blueprint has no routes attached. Therefore, when it goes to assign the exception handler it does it at the global level. If you take your example and add one new endpoint, it works as you would expect.

@handled.route("/ok")
def ok(request):
    raise Error("error in e")
╭─adam@hopkins ~/Projects/Sanic/sanic ‹main› 
╰─$ curl localhost:9999   
⚠️ 500 — Internal Server Error
==============================
error in e

Error: error in e while handling path /
Traceback of __main__ (most recent call last):

  Error: error in e
    File handle_request, line 81, in handle_request
    

    File /tmp/p.py, line 26, in e
    raise Error("error in e")
status=500  size=309 time=0.003229 content-type="text/plain; charset=utf-8"
╭─adam@hopkins ~/Projects/Sanic/sanic ‹main› 
╰─$ curl localhost:9999/ok
handled error in e
status=200  size=18 time=0.001932 content-type="text/plain; charset=utf-8"

I am not 100% sure if this is even a legitimate use case: having a blueprint with no routes. The simple answer is to just ignore the assignment if there are no routes.

@komar007
Copy link
Author

Thanks,

it works as expected.

The code from the OP is indeed not a sensible use case, just the simplest reproduction path.

@ahopkins
Copy link
Member

See #2246 with a fix to this.

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 a pull request may close this issue.

2 participants