def connection_lost(self, exc): self.connections.discard(self) if self.logger.level <= TRACE_LOG_LEVEL: prefix = "%s:%d - " % tuple(self.client) if self.client else "" self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection lost", prefix) if self.cycle and not self.cycle.response_complete: self.cycle.disconnected = True if self.conn.our_state != h11.ERROR: event = h11.ConnectionClosed() try: self.conn.send(event) except h11.LocalProtocolError: # Premature client disconnect pass if self.cycle is not None: self.cycle.message_event.set() if self.flow is not None: self.flow.resume_writing() if exc is None: self.transport.close() if self.on_connection_lost is not None: self.on_connection_lost()
def timeout_keep_alive_handler(self): """ Called on a keep-alive connection if no new data is received after a short delay. """ if not self.transport.is_closing(): event = h11.ConnectionClosed() self.conn.send(event) self.transport.close()
async def close(self) -> None: event = h11.ConnectionClosed() try: self.h11_state.send(event) except h11.LocalProtocolError: # pragma: no cover # Premature client disconnect pass await self.writer.close()
def close(self) -> None: if self._state != ConnectionState.CLOSED: self._state = ConnectionState.CLOSED if self._h11_state.our_state is h11.MUST_CLOSE: event = h11.ConnectionClosed() self._h11_state.send(event) self.socket.close()
async def close(self) -> None: event = h11.ConnectionClosed() try: logger.trace(f"send_event event={event!r}") self.h11_state.send(event) except h11.LocalProtocolError: # pragma: no cover # Premature client disconnect pass await self.stream.close()
async def aclose(self) -> None: if self.state != ConnectionState.CLOSED: self.state = ConnectionState.CLOSED if self.h11_state.our_state is h11.MUST_CLOSE: event = h11.ConnectionClosed() self.h11_state.send(event) await self.socket.aclose()
def shutdown(self): """ Called by the server to commence a graceful shutdown. """ if self.cycle is None or self.cycle.response_complete: event = h11.ConnectionClosed() self.conn.send(event) self.transport.close() else: self.cycle.keep_alive = False
def connection_lost(self, exc): if self.access_logs: self.logger.debug("%s - Disconnected", self.server[0]) if self.cycle and self.cycle.more_body: self.cycle.disconnected = True if self.conn.our_state != h11.ERROR: event = h11.ConnectionClosed() self.conn.send(event) self.client_event.set()
async def close(self) -> None: event = h11.ConnectionClosed() try: # If we're in h11.MUST_CLOSE then we'll end up in h11.CLOSED. self.h11_state.send(event) except h11.ProtocolError: # If we're in some other state then it's a premature close, # and we'll end up in h11.ERROR. pass await self.writer.close()
def connection_lost(self, exc): if self.access_logs: self.logger.debug("%s - Disconnected", self.server[0]) if self.cycle and not self.cycle.response_complete: self.cycle.disconnected = True if self.conn.our_state != h11.ERROR: event = h11.ConnectionClosed() try: self.conn.send(event) except h11.LocalProtocolError: # Premature client disconnect pass self.client_event.set()
def connection_lost(self, exc): self.connections.discard(self) if self.logger.level <= logging.DEBUG: self.logger.debug("%s - Disconnected", self.client) if self.cycle and not self.cycle.response_complete: self.cycle.disconnected = True if self.conn.our_state != h11.ERROR: event = h11.ConnectionClosed() try: self.conn.send(event) except h11.LocalProtocolError: # Premature client disconnect pass self.message_event.set()
async def recv_http_websocket(websocket): data = b'' event_list = [] conn = h11.Connection(h11.SERVER) while True: event = conn.next_event() if event is h11.NEED_DATA: #dat = await asyncio.wait_for(websocket.recv(2048), timeout=timeout) dat = await asyncio.wait_for(websocket.recv(), timeout=timeout) data += dat conn.receive_data(dat) elif event == h11.EndOfMessage(): break elif event == h11.ConnectionClosed(): print("ConnectionClosed detected") break else: event_list.append(event) return event_list, data
async def close(self) -> None: event = h11.ConnectionClosed() self.h11_state.send(event) await self.writer.close()
async def send(self, message): message_type = message["type"] if self.flow.write_paused and not self.disconnected: await self.flow.drain() if self.disconnected: return if not self.response_started: # Sending response status line and headers if message_type != "http.response.start": msg = "Expected ASGI message 'http.response.start', but got '%s'." raise RuntimeError(msg % message_type) self.response_started = True self.waiting_for_100_continue = False status_code = message["status"] headers = self.default_headers + message.get("headers", []) if self.access_log: self.logger.info( '%s - "%s %s HTTP/%s" %d', self.scope["client"], self.scope["method"], get_path_with_query_string(self.scope), self.scope["http_version"], status_code, extra={"status_code": status_code, "scope": self.scope}, ) # Write response status line and headers reason = STATUS_PHRASES[status_code] event = h11.Response( status_code=status_code, headers=headers, reason=reason ) output = self.conn.send(event) self.transport.write(output) elif not self.response_complete: # Sending response body if message_type != "http.response.body": msg = "Expected ASGI message 'http.response.body', but got '%s'." raise RuntimeError(msg % message_type) body = message.get("body", b"") more_body = message.get("more_body", False) # Write response body if self.scope["method"] == "HEAD": event = h11.Data(data=b"") else: event = h11.Data(data=body) output = self.conn.send(event) 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 send(self, message): message_type = message["type"] if self.flow.write_paused and not self.disconnected: await self.flow.drain() if self.disconnected: return if self.gunicorn_atoms is not None: self.gunicorn_atoms.on_asgi_message(message) if not self.response_started: # Sending response status line and headers if message_type != "http.response.start": msg = "Expected ASGI message 'http.response.start', but got '%s'." raise RuntimeError(msg % message_type) self.response_started = True self.waiting_for_100_continue = False status_code = message["status"] headers = self.default_headers + message.get("headers", []) if CLOSE_HEADER in self.scope[ "headers"] and CLOSE_HEADER not in headers: headers = headers + [CLOSE_HEADER] if self.access_log and self.gunicorn_log is None: self.access_logger.info( '%s - "%s %s HTTP/%s" %d', get_client_addr(self.scope), self.scope["method"], get_path_with_query_string(self.scope), self.scope["http_version"], status_code, ) # Write response status line and headers reason = STATUS_PHRASES[status_code] event = h11.Response(status_code=status_code, headers=headers, reason=reason) output = self.conn.send(event) self.transport.write(output) elif not self.response_complete: # Sending response body if message_type != "http.response.body": msg = "Expected ASGI message 'http.response.body', but got '%s'." raise RuntimeError(msg % message_type) body = message.get("body", b"") more_body = message.get("more_body", False) # Write response body if self.scope["method"] == "HEAD": event = h11.Data(data=b"") else: event = h11.Data(data=body) output = self.conn.send(event) self.transport.write(output) # Handle response completion if not more_body: self.response_complete = True self.message_event.set() event = h11.EndOfMessage() output = self.conn.send(event) self.scope["response_end_time"] = time.monotonic() if self.gunicorn_log is not None: try: self.gunicorn_log.access_log.info( self.gunicorn_log.cfg.access_log_format, self.gunicorn_atoms, ) except: # noqa self.gunicorn_log.error(traceback.format_exc()) 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 handle_http(reader, writer): # client info addr = writer.get_extra_info("peername") print("start to handle the request from client {}...".format(addr)) # parse the http request # read client data conn = h11.Connection(h11.SERVER) print("h11 states: {}".format(conn.states)) request_raw = b"" request_header = None request_body = None # 1. read the header # h11 event is expected to be h11.Request after proceeding print("reading header in the request...") event = None while True: data = await reader.read(recv_size) # reader.read(max_size) print("read chunk: {}".format(data)) request_raw += data conn.receive_data(data) event = conn.next_event() print("h11 event is {}".format(type(event))) if type(event) is h11.NEED_DATA: continue elif type(event) is h11.Request: print("the header is {}".format(event)) request_header = event break else: print("server paused") break print("h11 states {}".format(conn.states)) # 2. read the body # h11 event is expected to be h11.EndOfMessage or h11.DATA after proceeding print("reading body in the request...") if type(event) is h11.Request: event = conn.next_event() if type(event) is h11.EndOfMessage: print("the body is empty, and stop reading from reader stream") elif type(event) is h11.NEED_DATA: print( "the body has content, and keep on reading from reader stream") while True: data = await reader.read(recv_size) # reader.read(max_size) print("read chunk: {}".format(data)) conn.receive_data(data) request_raw += data event = conn.next_event() print("h11 event is {}".format(type(event))) if type(event) is h11.NEED_DATA: continue elif type(event) is h11.DATA: print("the body is {}".format(event)) request_body = event break else: break else: print("unexpected event {}".format(event)) print("h11 states {}".format(conn.states)) # 3. finish the request reading # h11 event is expected to be h11.EndOfMessage after proceeding print("finishing the request reading...") if type(event) is h11.Data: event = conn.next_event() if event is h11.EndOfMessage: print("complete request reading") pass else: print("unexpected event {}".format(event)) elif type(event) is h11.EndOfMessage: print("complete request reading") pass else: print("unexpected event {}".format(event)) print("h11 states {}".format(conn.states)) # 4. prepare the response print("preparing the response...") h11_response_header = None h11_response_body = None if type(event) is h11.EndOfMessage: # TODO: response = await send_data_to_destination() # compose a `text/plain` content type response message = "received" h11_response_header, h11_response_body = text_response(message) else: print("unexpected event {}".format(event)) message = "server error" h11_response_header, h11_response_body = text_response(message) # 5. send the response to client print("sending the response to client {}".format(addr)) # header data = conn.send(h11_response_header) writer.write(data) print("send header: {}".format(data)) print("h11 states {}".format(conn.states)) # body data = conn.send(h11_response_body) writer.write(data) print("send body: {}".format(data)) print("h11 states {}".format(conn.states)) # eof data = conn.send(h11.EndOfMessage()) writer.write(data) print("send eof: {}".format(data)) print("h11 states {}".format(conn.states)) await writer.drain() # 6. close the client print("close the client socket") conn.send(h11.ConnectionClosed()) print("h11 states {}".format(conn.states)) writer.close()
def just_close(client_handler): """ Just end the response without informing about conneciton close. """ client_handler.http_send(h11.ConnectionClosed())
def finish(client_handler): """ End the response gracefully. """ client_handler.http_send(h11.EndOfMessage()) client_handler.http_send(h11.ConnectionClosed())
def close(self): self.send(h11.ConnectionClosed()) self.writer.close()
async def send(self, message): global DEFAULT_HEADERS protocol = self.protocol message_type = message["type"] if self.disconnected: return if not protocol.writable: await protocol.writable_event.wait() if not self.response_started: # Sending response status line and headers if message_type != "http.response.start": msg = "Expected ASGI message 'http.response.start', but got '%s'." raise RuntimeError(msg % message_type) self.response_started = True status_code = message["status"] headers = DEFAULT_HEADERS + message.get("headers", []) if protocol.access_logs: protocol.logger.info( '%s - "%s %s HTTP/%s" %d', self.scope["server"][0], self.scope["method"], self.scope["path"], self.scope["http_version"], status_code, ) # Write response status line and headers reason = STATUS_PHRASES[status_code] event = h11.Response(status_code=status_code, headers=headers, reason=reason) output = protocol.conn.send(event) protocol.transport.write(output) elif not self.response_complete: # Sending response body if message_type != "http.response.body": msg = "Expected ASGI message 'http.response.body', but got '%s'." raise RuntimeError(msg % message_type) body = message.get("body", b"") more_body = message.get("more_body", False) # Write response body event = h11.Data(data=body) output = protocol.conn.send(event) protocol.transport.write(output) # Handle response completion if not more_body: self.response_complete = True event = h11.EndOfMessage() output = protocol.conn.send(event) protocol.transport.write(output) else: # Response already sent msg = "Unexpected ASGI message '%s' sent, after response already completed." raise RuntimeError(msg % message_type) if protocol.conn.our_state is h11.MUST_CLOSE: event = h11.ConnectionClosed() protocol.conn.send(event) protocol.transport.close() elif (protocol.conn.our_state is h11.DONE and protocol.conn.their_state is h11.DONE): protocol.resume_reading() protocol.conn.start_next_cycle()
def finish_and_close(self): """Cleanly finish and close the connection.""" self.conn.send(h11.ConnectionClosed()) self.close()