sanic-org / sanic

Accelerate your web app development | Build fast. Run fast.

Home Page:https://sanic.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

FALLBACK_ERROR_FORMAT does not work with empty()

simon-lund opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Today I tested a handler which always returns empty() (see example below).
I was quite confused by the format of the errors, as they were all in HTML format, even though the fallback was set to json.
It took me a while to figure out that this was because of the empty() statement returned by the function, which somehow hijacks the error format, so that the errors are converted to html.

I could use the error_format from now on for handlers returning empty(), but was wondering if this is a feature or a bug.

Code snippet

from sanic import Sanic, empty
from sanic.exceptions import Unauthorized


app = Sanic(__name__)
app.config.FALLBACK_ERROR_FORMAT = "json"

# Returns error in html format
@app.post("/empty")
async def empty_(request):
    raise Unauthorized("bli bla blub")

    return empty()

# Returns error in json format
@app.post("/nothing")
async def nothing(request):
    raise Unauthorized("bli bla blub")


if __name__ == '__main__':
    app.run("127.0.0.1", port=3000, auto_reload=True, debug=True, dev=True)

How do you run Sanic?

As a script

Operating System

Ubuntu

Sanic Version

22.9.1

Triage. Sanic tries to determine the response type automatically using various heuristics. The one you hit is that the handler returns empty(), which Sanic maps to HTML and considers the case solved, no fallback, error page in HTML. @ahopkins Can we make empty() unopinionated and use the fallback instead?

One way to avoid this is to add an accept: application/json header to your requests, then Sanic will always respond in JSON and not use any of these heuristics.

@simon-lund Thanks for the report and a useful test case, made triaging much easier! The heuristics are quite complicated but we can probably let empty run to the fallback which also gets what you need without the header.

Thanks for the quick response 👍 and explaining how it works under the hood. Very interesting.

@Tronic I also didn't know about the Accept-Header. It's not in the docs. You think I could add a note about this?

@Tronic I also didn't know about the Accept-Header. It's not in the docs. You think I could add a note about this?

We will need to comprehensively document the error handling side, if/when the related PRs land. Overall, we are planning some much needed work on the Sanic guide. The accept header per se is standard stuff and some JSON APIs require it to be set to application/json to give any response.