Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
self.transport.write(output)
# Handle response completion
if not more_body:
self.response_complete = True
event = h11.EndOfMessage()
output = self.conn.send(event)
self.transport.write(output)
else:
# Response already sent
msg = "Unexpected ASGI message '%s' sent, after response already completed."
raise RuntimeError(msg % message_type)
if self.response_complete:
if self.conn.our_state is h11.MUST_CLOSE or not self.keep_alive:
event = h11.ConnectionClosed()
self.conn.send(event)
self.transport.close()
self.on_response()
async def maybe_close(connection: h11.Connection,
response_writer: asyncio.StreamWriter):
"""
Ensures whether there's a need to close the connection or keep using it
:param connection: h11 server connection object
:param response_writer:
:return: None
"""
log.log("server state: {0}".format(connection.our_state))
log.log("attempting to close connection")
await send_eof_and_close(
response_writer,
close_writer=connection.our_state is h11.MUST_CLOSE
)
if isinstance(event, h11.Request):
headers = CIMultiDict()
for name, value in event.headers:
headers.add(name.decode().title(), value.decode())
self.handle_request(
0, event.method.decode().upper(), event.target.decode(), headers,
)
elif isinstance(event, h11.EndOfMessage):
self.streams[0].complete()
elif isinstance(event, h11.Data):
self.streams[0].append(event.data)
elif event is h11.NEED_DATA or event is h11.PAUSED:
break
elif isinstance(event, h11.ConnectionClosed):
break
if self.connection.our_state is h11.MUST_CLOSE:
self.close()
while True:
assert wrapper.conn.states == {
h11.CLIENT: h11.IDLE, h11.SERVER: h11.IDLE}
try:
with trio.move_on_after(TIMEOUT):
wrapper.info("Server main loop waiting for request")
event = await wrapper.next_event()
wrapper.info("Server main loop got event:", event)
if type(event) is h11.Request:
await request_handler(wrapper, event)
except Exception as exc:
wrapper.info("Error during response handler:", exc)
await maybe_send_error_response(wrapper, exc)
if wrapper.conn.our_state is h11.MUST_CLOSE:
wrapper.info("connection is not reusable, so shutting down")
await wrapper.shutdown_and_clean_up()
return
else:
try:
wrapper.info("trying to re-use connection")
wrapper.conn.start_next_cycle()
except h11.LocalProtocolError:
wrapper.info("not in a reusable state")
return
except h11.ProtocolError:
states = wrapper.conn.states
wrapper.info("unexpected state", states, "-- bailing out")
await maybe_send_error_response(
wrapper,
RuntimeError("unexpected state {}".format(states)))
while True:
assert wrapper.conn.states == {
h11.CLIENT: h11.IDLE, h11.SERVER: h11.IDLE}
try:
with trio.fail_after(TIMEOUT):
wrapper.info("Server main loop waiting for request")
event = await wrapper.next_event()
wrapper.info("Server main loop got event:", event)
if type(event) is h11.Request:
await send_echo_response(wrapper, event)
except Exception as exc:
wrapper.info("Error during response handler:", exc)
await maybe_send_error_response(wrapper, exc)
if wrapper.conn.our_state is h11.MUST_CLOSE:
wrapper.info("connection is not reusable, so shutting down")
await wrapper.shutdown_and_clean_up()
return
else:
try:
wrapper.info("trying to re-use connection")
wrapper.conn.start_next_cycle()
except h11.ProtocolError:
states = wrapper.conn.states
wrapper.info("unexpected state", states, "-- bailing out")
await maybe_send_error_response(
wrapper,
RuntimeError("unexpected state {}".format(states)))
await wrapper.shutdown_and_clean_up()
return
def _cleanup_after_received(self):
self._req = None
self._resp = None
self._body_chunks = []
if self.our_state is h11.MUST_CLOSE:
self.io_stream.close()
event = await transport.next_event()
log.info(f"Server main loop got event: {event}")
if type(event) is h11.Request:
request = Request(event)
handler = self.router.match(request)
status, response = await handler(request)
content_type, response = response_to_bytes(handler, response)
await respond(status, content_type, response)
except Exception as exc:
log.info(f"Error during response handler: {exc}")
handler = self.router.match_error(exc)
status, response = await handler(exc)
content_type, response = response_to_bytes(handler, response)
await respond(status, content_type, response)
if transport.conn.our_state is h11.MUST_CLOSE:
log.info("connection is not reusable, so shutting down")
await transport.shutdown_and_clean_up()
return
else:
try:
log.info("trying to re-use connection")
transport.conn.start_next_cycle()
except h11.ProtocolError:
states = transport.conn.states
log.info(f"unexpected state {states} -- bailing out")
exc = RuntimeError("unexpected state {}".format(states))
handler = self.router.match_error(exc)
status, response = await handler(exc)
content_type, response = response_to_bytes(handler, response)
await respond(status, content_type, response)
await transport.shutdown_and_clean_up()
for name, value in event.headers:
headers.add(name.decode().title(), value.decode())
if 'Upgrade' in headers:
self._handle_upgrade_request(headers, event)
self.handle_request(
0, event.method.decode().upper(), event.target.decode(), headers,
)
elif isinstance(event, h11.EndOfMessage):
self.streams[0].complete()
elif isinstance(event, h11.Data):
self.streams[0].append(event.data)
elif event is h11.NEED_DATA or event is h11.PAUSED:
break
elif isinstance(event, h11.ConnectionClosed):
break
if self.connection.our_state is h11.MUST_CLOSE:
self.close()
async def http_serve(sock, addr):
wrapper = CurioHTTPWrapper(sock)
while True:
assert wrapper.conn.states == {
h11.CLIENT: h11.IDLE, h11.SERVER: h11.IDLE}
try:
async with curio.timeout_after(TIMEOUT):
event = await wrapper.next_event()
if type(event) is h11.Request:
await send_echo_response(wrapper, event)
except Exception as exc:
await maybe_send_error_response(wrapper, exc)
if wrapper.conn.our_state is h11.MUST_CLOSE:
await wrapper.shutdown_and_clean_up()
return
else:
try:
wrapper.conn.start_next_cycle()
except h11.ProtocolError:
states = wrapper.conn.states
await maybe_send_error_response(
wrapper,
RuntimeError("unexpected state {}".format(states)))
await wrapper.shutdown_and_clean_up()
return
async def _handle_events(self) -> None:
while True:
if self.connection.they_are_waiting_for_100_continue:
await self._send_h11_event(
h11.InformationalResponse(
status_code=100, headers=self.config.response_headers("h11")
)
)
if self.connection.our_state in {h11.DONE, h11.CLOSED, h11.MUST_CLOSE}:
return
try:
event = self.connection.next_event()
except h11.RemoteProtocolError:
if self.connection.our_state in {h11.IDLE, h11.SEND_RESPONSE}:
await self._send_error_response(400)
await self.send(Closed())
break
else:
if isinstance(event, h11.Request):
await self._check_protocol(event)
await self._create_stream(event)
elif isinstance(event, h11.Data):
await self.stream.handle(Body(stream_id=STREAM_ID, data=event.data))
elif isinstance(event, h11.EndOfMessage):