12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- """
- Hypertext Transfer Protocol.
- """
- from pypacker import pypacker, triggerlist
- import re
- import logging
- logger = logging.getLogger("pypacker")
- class HTTPStartLine(triggerlist.TriggerList):
- def _pack(self):
- # logger.debug("packing HTTP-header")
- # no header = no CRNL
- if len(self) == 0:
- # logger.debug("empty buf 2")
- return b""
- return b"".join(self) + b"\r\n"
- class HTTPHeader(triggerlist.TriggerList):
- def _pack(self):
- # logger.debug("packing HTTP-header")
- # no header = no CRNL
- if len(self) == 0:
- # logger.debug("empty buf 2")
- return b""
- return b"\r\n".join([b": ".join(keyval) for keyval in self]) + b"\r\n\r\n"
- # REQ_METHODS_BASIC = set([b"GET", b"POST", b"HEAD", b"PUT", b"OPTIONS", b"CONNECT", b"UPDATE", b"TRACE"])
- PROG_SPLIT_HEADBODY = re.compile(b"\r\n\r\n")
- PROG_SPLIT_HEADER = re.compile(b"\r\n")
- PROG_SPLIT_KEYVAL = re.compile(b": ")
- class HTTP(pypacker.Packet):
- __hdr__ = (
- # content: ["startline"]
- ("startline", None, HTTPStartLine),
- # content: [("name", "value"), ...]
- ("hdr", None, HTTPHeader),
- )
- def _dissect(self, buf):
- # requestline: [method] [uri] [version] eg GET / HTTP/1.1
- # responseline: [version] [status] [reason] eg HTTP/1.1 200 OK
- # TODO: raises exception on reader
- try:
- bts_header, bts_body = PROG_SPLIT_HEADBODY.split(buf, 1)
- except ValueError:
- # assume this is part of a bigger (splittet) HTTP-message (no header)
- return len(buf)
- # logger.debug("head: %s" % bts_header)
- # logger.debug("body: %s" % bts_body)
- startline, bts_header = PROG_SPLIT_HEADER.split(bts_header, 1)
- # logger.debug("startline: %s" % startline)
- # logger.debug("bts_header: %s" % bts_header)
- self._init_triggerlist("startline", startline + b"\r\n", lambda bts: bts.strip())
- self._init_triggerlist("hdr", bts_header + b"\r\n\r\n", self.__parse_header)
- # logger.debug(self.startline.bin())
- # logger.debug(self.header.bin())
- # logger.debug(len(startline+b"\r\n") + len(bts_header+b"\r\n\r\n"))
- # logger.debug("lengths head/body: %d %d" % (len(buf), len(bts_body)))
- # logger.debug(buf[:len(buf) - len(bts_body)])
- # HEADER + "\r\n\r\n" + BODY -> newline is part of the header
- return len(buf) - len(bts_body)
- @staticmethod
- def __parse_header(buf):
- # logger.debug("parsing: %s" % buf)
- header = []
- lines = PROG_SPLIT_HEADER.split(buf)
- for line in lines:
- # logger.debug("checking HTTP-header: %s" % line)
- if len(line) == 0:
- break
- key, val = PROG_SPLIT_KEYVAL.split(line, 1)
- header.append((key, val))
- return header
|