def validate_request_uri_scheme(self): if self.message.uri.scheme: if self.message.uri.scheme not in ('http', 'https'): exc = InvalidURI(_(u'Invalid URL: wrong scheme')) raise BAD_REQUEST(Unicode(exc)) else: self.message.uri.scheme = self._default_scheme self.message.uri.host = self._default_host self.message.uri.port = self._default_port
def __parse_chunk_size(self): line, rest_chunk = self.buffer.split(self.line_end, 1) chunk_size = line.split(b";", 1)[0].strip() try: chunk_size = int(bytes(chunk_size), 16) if chunk_size < 0: raise ValueError except (ValueError, OverflowError): exc = InvalidHeader(_(u'Invalid chunk size: %r'), chunk_size.decode('ISO8859-1')) raise BAD_REQUEST(Unicode(exc)) else: return chunk_size, rest_chunk
def parse(self, data): u"""Appends the given data to the internal buffer and parses it as HTTP Request-Messages. :param data: data to parse :type data: bytes """ self.buffer.extend(data) try: return tuple(x for x in self._parse() if x is not None) except (InvalidHeader, InvalidLine, InvalidURI) as exc: raise BAD_REQUEST(Unicode(exc))
def merge_trailer_into_header(self): message = self.message for name in message.headers.values('Trailer'): value = self.trailers.pop(name, None) if value is not None: message.headers.append(name, value) else: # ignore pass if self.trailers: msg_trailers = u'" ,"'.join(self.trailers.keys()) raise BAD_REQUEST(u'untold trailers: "%s"' % msg_trailers) del self.trailers
def parse_startline(self): if CRLF not in self.buffer: if LF not in self.buffer: return NOT_RECEIVED_YET self.line_end = LF requestline, self.buffer = self.buffer.split(self.line_end, 1) # parse request line try: self.message.parse(bytes(requestline)) except (InvalidLine, InvalidURI) as exc: raise BAD_REQUEST(Unicode(exc))
def parse_headers(self): # empty headers? if self.buffer.startswith(self.line_end): self.buffer = self.buffer[len(self.line_end):] return False header_end = self.line_end + self.line_end if header_end not in self.buffer: # headers incomplete return NOT_RECEIVED_YET headers, self.buffer = self.buffer.split(header_end, 1) # parse headers if headers: try: self.message.headers.parse(bytes(headers)) except InvalidHeader as exc: raise BAD_REQUEST(Unicode(exc))
def determine_message_length(self): # RFC 2616 Section 4.4 # get message length # TODO: check if both is set message = self.message if 'Transfer-Encoding' in message.headers and message.protocol >= (1, 1): # chunked transfer in HTTP/1.1 te = message.headers['Transfer-Encoding'].lower() self.chunked = 'chunked' == te if not self.chunked: raise NOT_IMPLEMENTED(u'Unknown HTTP/1.1 Transfer-Encoding: %r' % te) else: # Content-Length header defines the length of the message body try: self.message_length = int(message.headers.get("Content-Length", "0")) if self.message_length < 0: self.message_length = None raise ValueError except ValueError: raise BAD_REQUEST(_(u'Invalid Content-Length header.'))
def parse_trailers(self): # TODO: the code is exactly the same as parse_headers but # we have to make sure no invalid header fields are send (only values told in Trailer header allowed) if self.buffer.startswith(self.line_end): self.buffer = self.buffer[len(self.line_end):] return False # no trailers trailer_end = self.line_end + self.line_end if trailer_end not in self.buffer: # not received yet return NOT_RECEIVED_YET trailers, self.buffer = self.buffer.split(trailer_end, 1) self.trailers = Headers() try: self.trailers.parse(bytes(trailers)) except InvalidHeader as exc: exc = InvalidHeader(_(u'Invalid trailers: %r'), Unicode(exc)) raise BAD_REQUEST(Unicode(exc)) self.merge_trailer_into_header() return False
def check_methods_without_body(self): if self.message.method in (u'HEAD', u'GET', u'TRACE') and self.message.body: raise BAD_REQUEST( 'A %s request is considered as safe and MUST NOT contain a request body.' % self.message.method)
def check_host_header_exists(self): if self.message.protocol >= (1, 1) and 'Host' not in self.message.headers: raise BAD_REQUEST('Missing Host header')