blindChicken
blindChicken

Reputation: 392

Python Quart/Hypercorn streamed response causing net::ERR_HTTP2_PROTOCOL_ERROR 200

I have a Quart app with which I stream a response back to the client. I am using asyncio.sleep to delay the response completion, if I set the delay to 59 seconds everythings works fine. The stream completes without any issue. If I increase the time to 120 seconds, the response appears to timeout. That is the first part of the stream is received by the client but after about 60 seconds the browser throws an error in Chrome it is: net::ERR_HTTP2_PROTOCOL_ERROR 200. Firefox throws a TypeError.

I am using Hypercorn with Nginx.

the hypercorn config.py file reads:

Shutdown_timeout = 123.0
ssl_handshake_timeout = 123.0
startup_timeout = 123.0

the relevant setting in nginx.conf:

location @proxy_to_app {
proxy_read_timout = 600s
}

I do not know how to solve this.

I figured out the source of the problem. It has nothing to do with Quart, Hypercorn or Nginx. The problem is with Cloudflare and http2, it is caused by a WriteTimeout. See this answer: What's the net::ERR_HTTP2_PROTOCOL_ERROR about?

The question then is, how to change this in Cloudlfare.

I do not have Quart configured to work in http2, would that help?

Upvotes: 0

Views: 1430

Answers (1)

blindChicken
blindChicken

Reputation: 392

The only solution I found was to break the sleep up and send interim data to the client in order to keep the connection alive.

async def async_generator():
      content_arr = [
          json.dumps({'first':'some data'}),
          json.dumps({'alive':''}),  #required to http2 connection alive
          json.dumps({'final' : 'final data'})
      ]
      for i,html in enumerate(content_arr):
          print(i)
          if i > 0:
              await asyncio.sleep(59)  #this delays sending the final data 118 seconds
          yield html.encode()

Upvotes: 1

Related Questions