def expect_handler(self): """ Handler for Expect Header. """ expect = self.request.headers.get(EXPECT_HEADER) if self.request.version == "1.1": if expect.lower() == "100-continue": self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n") else: self.write_error( HeaderExpectationFailed(f"Unknown Expect: {expect}"))
async def http1_request_header(self): """ Receive and parse request header into self.request. """ HEADER_MAX_SIZE = min(8192, self.request_max_size) # Receive until full header is in buffer buf = self.recv_buffer pos = 0 while True: pos = buf.find(b"\r\n\r\n", pos) if pos != -1: break pos = max(0, len(buf) - 3) if pos >= HEADER_MAX_SIZE: break await self._receive_more() if pos >= HEADER_MAX_SIZE: raise PayloadTooLarge("Request header exceeds the size limit") # Parse header content try: head = buf[:pos] raw_headers = head.decode(errors="surrogateescape") reqline, *split_headers = raw_headers.split("\r\n") method, self.url, protocol = reqline.split(" ") if protocol == "HTTP/1.1": self.keep_alive = True elif protocol == "HTTP/1.0": self.keep_alive = False else: raise Exception # Raise a Bad Request on try-except self.head_only = method.upper() == "HEAD" request_body = False headers = [] for name, value in (h.split(":", 1) for h in split_headers): name, value = h = name.lower(), value.lstrip() if name in ("content-length", "transfer-encoding"): request_body = True elif name == "connection": self.keep_alive = value.lower() == "keep-alive" headers.append(h) except Exception: raise InvalidUsage("Bad Request") headers_instance = Header(headers) self.upgrade_websocket = (headers_instance.get( "upgrade", "").lower() == "websocket") # Prepare a Request object request = self.protocol.request_class( url_bytes=self.url.encode(), headers=headers_instance, head=bytes(head), version=protocol[5:], method=method, transport=self.protocol.transport, app=self.protocol.app, ) # Prepare for request body self.request_bytes_left = self.request_bytes = 0 if request_body: headers = request.headers expect = headers.get("expect") if expect is not None: if expect.lower() == "100-continue": self.expecting_continue = True else: raise HeaderExpectationFailed(f"Unknown Expect: {expect}") if headers.get("transfer-encoding") == "chunked": self.request_body = "chunked" pos -= 2 # One CRLF stays in buffer else: self.request_body = True self.request_bytes_left = self.request_bytes = int( headers["content-length"]) # Remove header and its trailing CRLF del buf[:pos + 4] self.stage = Stage.HANDLER self.request, request.stream = request, self self.protocol.state["requests_count"] += 1