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

Nicer error handling with mishandled responses #2219

Closed
ahopkins opened this issue Aug 17, 2021 · 2 comments
Closed

Nicer error handling with mishandled responses #2219

ahopkins opened this issue Aug 17, 2021 · 2 comments

Comments

@ahopkins
Copy link
Member

@app.get("/")
async def handler(request):
    response1 = await request.respond(headers={"one": "one"})
    response2 = await request.respond(headers={"two": "two"})

    await response1.send("One")
    await response2.send("Two")

    await response1.eof()
    await response2.send("???")
    await response2.eof()
$ curl localhost:9999 -i
HTTP/1.1 200 OK
one: one
transfer-encoding: chunked
connection: keep-alive
content-type: None

OneTwo
[2021-08-17 15:14:06 +0300] [368537] [ERROR] Exception occurred while handling uri: 'http://localhost:9999/'
Traceback (most recent call last):
  File "handle_request", line 83, in handle_request
    """
  File "/tmp/p.py", line 21, in handler
    await response2.send("???")
  File "/home/adam/Projects/Sanic/sanic/sanic/response.py", line 122, in send
    await self.stream.send(data, end_stream=end_stream)
TypeError: 'NoneType' object is not callable

Two things here:

  1. When we create the second response, there is no indication to the user that this is somewhat useless. The headers here are ignored, although you can continue sending from it. As seen in example.
  2. When send is called after the eof, there should be a nicer error than NoneType that does not explain what happened to the stream.
@ChihweiLHBird
Copy link
Member

Should has been fixed in #2327

@ChihweiLHBird
Copy link
Member

@app.get("/case1")
async def handler(request):
    response1 = await request.respond(headers={"one": "one"})
    response2 = await request.respond(headers={"two": "two"})

    await response1.send("One")
    await response2.send("Two")

    await response1.eof()
    await response2.send("???")
    await response2.eof()

@app.get("/case2")
async def handler(request):
    response1 = await request.respond(headers={"one": "one"})

    await response1.send("One")

    await response1.eof()
    await response1.send("Two")


app.run()

Log:

[2021-12-09 15:33:54 -0600] [1606] [ERROR] Exception occurred while handling uri: 'http://localhost:8000/case1'
Traceback (most recent call last):
  File "handle_request", line 83, in handle_request
    from sanic.models.handler_types import Sanic as SanicVar
  File "test.py", line 87, in handler
    response2 = await request.respond(headers={"two": "two"})
  File "/home/chihwei/sanic/sanic/request.py", line 194, in respond
    raise ServerError("Second respond call is not allowed.")
sanic.exceptions.ServerError: Second respond call is not allowed.
[2021-12-09 15:33:54 -0600] - (sanic.access)[INFO][127.0.0.1:34278]: GET http://localhost:8000/case1  500 760
[2021-12-09 15:34:03 -0600] - (sanic.access)[INFO][127.0.0.1:34280]: GET http://localhost:8000/case2  200 3
[2021-12-09 15:34:03 -0600] [1606] [ERROR] Response stream was ended, no more response data is allowed to be sent.
Traceback (most recent call last):
  File "handle_request", line 83, in handle_request
    from sanic.models.handler_types import Sanic as SanicVar
  File "test.py", line 103, in handler
    await response1.send("Two")
  File "/home/chihwei/sanic/sanic/response.py", line 127, in send
    raise ServerError(
sanic.exceptions.ServerError: Response stream was ended, no more response data is allowed to be sent.
[2021-12-09 15:34:03 -0600] [1606] [ERROR] The error response will not be sent to the client for the following exception:"Response stream was ended, no more response data is allowed to be sent.". A previous response has at least partially been sent.

Response:

(.venv) user@COMPUTER:~/sanic$ curl http://localhost:8000/case1
<!DOCTYPE html><html lang=en><meta charset=UTF-8><title>⚠️ 500 — Internal Server Error</title>
<style>
        html { font-family: sans-serif }
        h2 { color: #888; }
        .tb-wrapper p, dl, dd { margin: 0 }
        .frame-border { margin: 1rem }
        .frame-line > *, dt, dd { padding: 0.3rem 0.6rem }
        .frame-line, dl { margin-bottom: 0.3rem }
        .frame-code, dd { font-size: 16px; padding-left: 4ch }
        .tb-wrapper, dl { border: 1px solid #eee }
        .tb-header,.obj-header {
            background: #eee; padding: 0.3rem; font-weight: bold
        }
        .frame-descriptor, dt { background: #e2eafb; font-size: 14px }
    </style>
<h1>⚠️ 500 — Internal Server Error</h1><p>Second respond call is not allowed.
(.venv) user@COMPUTER:~/sanic$ curl http://localhost:8000/case2
One

The new version will behave like above.

@ahopkins ahopkins closed this as completed Dec 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants