Beispiel #1
0
    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()
Beispiel #2
0
 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()
Beispiel #3
0
 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()
Beispiel #4
0
    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()
Beispiel #5
0
 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()
Beispiel #6
0
    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()
Beispiel #7
0
 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
Beispiel #8
0
    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()
Beispiel #9
0
    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()
Beispiel #10
0
    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()
Beispiel #11
0
    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()
Beispiel #12
0
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
Beispiel #13
0
 async def close(self) -> None:
     event = h11.ConnectionClosed()
     self.h11_state.send(event)
     await self.writer.close()
Beispiel #14
0
    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()
Beispiel #15
0
    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()
Beispiel #16
0
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()
Beispiel #17
0
def just_close(client_handler):
    """
    Just end the response without informing about conneciton close.
    """
    client_handler.http_send(h11.ConnectionClosed())
Beispiel #18
0
def finish(client_handler):
    """
    End the response gracefully.
    """
    client_handler.http_send(h11.EndOfMessage())
    client_handler.http_send(h11.ConnectionClosed())
Beispiel #19
0
 def close(self):
     self.send(h11.ConnectionClosed())
     self.writer.close()
Beispiel #20
0
    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()
Beispiel #21
0
 def finish_and_close(self):
     """Cleanly finish and close the connection."""
     self.conn.send(h11.ConnectionClosed())
     self.close()