Exemple #1
0
    def parse_request_line(self, line):
        bits = line.split(None, 2)
        if len(bits) != 3:
            raise ParseError("Invalid request line.")

        # Method
        if not self.methre.match(bits[0]):
            raise ParseError("Invalid request line. Bad method.")
        self.method = bits[0].upper()

        # URI
        self.uri = bits[1]
        parts = uri.parse(bits[1])
        self.scheme = parts["scheme"] or None
        self.userinfo = parts["userinfo"] or None
        self.host = parts["host"] or None
        if not parts["port"]:
            if self.scheme == b("http"):
                self.port = b("80")
            elif self.scheme == b("https"):
                self.port = b("443")
            else:
                self.port = None
        self.path = parts["path"] or None
        self.query = parts["query"] or None
        self.fragment = parts["fragment"] or None

        # Version
        match = self.versre.match(bits[2])
        if match is None:
            raise ParseError("Invalid HTTP version.")
        self.version = (int(match.group(1)), int(match.group(2)))
Exemple #2
0
    def parse_request_line(self, line):
        bits = line.split(None, 2)
        if len(bits) != 3:
            raise ParseError("Invalid request line.")

        # Method
        if not self.methre.match(bits[0]):
            raise ParseError("Invalid request line. Bad method.")
        self.method = bits[0].upper()

        # URI
        self.uri = bits[1]
        parts = uri.parse(bits[1])
        self.scheme = parts["scheme"] or None
        self.userinfo = parts["userinfo"] or None
        self.host = parts["host"] or None
        if not parts["port"]:
            if self.scheme == b("http"):
                self.port = b("80")
            elif self.scheme == b("https"):
                self.port = b("443")
            else:
                self.port = None
        self.path = parts["path"] or None
        self.query = parts["query"] or None
        self.fragment = parts["fragment"] or None

        # Version
        match = self.versre.match(bits[2])
        if match is None:
            raise ParseError("Invalid HTTP version.")
        self.version = (int(match.group(1)), int(match.group(2)))
Exemple #3
0
 def should_close(self):
     for (h, v) in self.headers:
         if h.lower() == b("connection"):
             if v.lower().strip() == b("close"):
                 return True
             elif v.lower().strip() == b("keep-alive"):
                 return False
     return self.version <= (1, 0)
Exemple #4
0
 def should_close(self):
     for (h, v) in self.headers:
         if h.lower() == b("connection"):
             if v.lower().strip() == b("close"):
                 return True
             elif v.lower().strip() == b("keep-alive"):
                 return False
     return self.version <= (1, 0)
Exemple #5
0
 def app(self, environ):
     status = 200
     body = pprint.pformat(environ).encode('latin-1')
     headers = [
         (b("Content-Type"), b("text/plain")),
         (b("Content-Length"), b(str(len(body))))
     ]
     return status, headers, [body]
Exemple #6
0
 def respond(self, status, headers, body):
     front = [b("HTTP/1.1 %d %s" % (status, STATUS_CODES[status]))]
     for name, value in headers:
         front.append(name + b(": ") + value)
     front.extend([b(""), b("")])
     self.started = True
     self.socket.send(b("\r\n").join(front))
     for data in body:
         self.socket.send(data)
Exemple #7
0
 def __init__(self, node, n=0, **params):
     super(Rep, self).__init__(**params)
     self.node = node
     if n == 0:
         self.n = b("*")
     elif n == 1:
         self.n = b("+")
     else:
         raise ValueError(n)
Exemple #8
0
 def __init__(self, node, n=0, **params):
     super(Rep, self).__init__(**params)
     self.node = node
     if n == 0:
         self.n = b("*")
     elif n == 1:
         self.n = b("+")
     else:
         raise ValueError(n)
Exemple #9
0
    def parse_headers(self, data):
        headers = []

        # Split lines on \r\n keeping the \r\n on each line
        lines = []
        while len(data):
            pos = data.find(b("\r\n"))
            if pos < 0:
                lines.append(data)
                data = b("")
            else:
                lines.append(data[:pos+2])
                data = data[pos+2:]

        # Parse headers into key/value pairs paying attention
        # to continuation lines.
        while len(lines):
            # Parse initial header name : value pair.
            curr = lines.pop(0)
            if curr.find(b(":")) < 0:
                raise ParseError("Invalid header. No colon separator found.")
            name, value = curr.split(b(":"), 1)
            name = name.rstrip(b(" \t")).upper()
            if self.hdrre.search(name):
                raise ParseError("Invalid header. Invalid bytes.")
            name, value = name.strip(), [value.lstrip()]
            
            # Consume value continuation lines
            while len(lines) and lines[0].startswith((b(" "), b("\t"))):
                value.append(lines.pop(0))
            value = b("").join(value).rstrip()
            
            headers.append((name, value))
        return headers
Exemple #10
0
    def parse_headers(self, data):
        headers = []

        # Split lines on \r\n keeping the \r\n on each line
        lines = []
        while len(data):
            pos = data.find(b("\r\n"))
            if pos < 0:
                lines.append(data)
                data = b("")
            else:
                lines.append(data[:pos + 2])
                data = data[pos + 2:]

        # Parse headers into key/value pairs paying attention
        # to continuation lines.
        while len(lines):
            # Parse initial header name : value pair.
            curr = lines.pop(0)
            if curr.find(b(":")) < 0:
                raise ParseError("Invalid header. No colon separator found.")
            name, value = curr.split(b(":"), 1)
            name = name.rstrip(b(" \t")).upper()
            if self.hdrre.search(name):
                raise ParseError("Invalid header. Invalid bytes.")
            name, value = name.strip(), [value.lstrip()]

            # Consume value continuation lines
            while len(lines) and lines[0].startswith((b(" "), b("\t"))):
                value.append(lines.pop(0))
            value = b("").join(value).rstrip()

            headers.append((name, value))
        return headers
Exemple #11
0
def check_environ(environ):
    # Keys covered in specific validaotors:
    #   http.body, wsgi.errors, wsgi.upgrade, wsgi.upgraded

    assert_(envrion["wsgi.version"] == (2, 0), "Invalid wsgi version.")
    
    for key in environ.keys():
        assert_(type(key) is STRING_TYPE, "Invalid environ key type.")

    basic_key_types = {
        BOOL_TYPE: """
                wsgi.multithread wsg.multiprocess
            """.split(),
        INT_TYPE: """
                conn.server_port conn.remote_port
            """.split(),
        BYTES_TYPE: """
                http.method http.uri.raw http.uri.path http.uri.query_string
                wsgi.url_scheme wsgi.script_name conn.server_name
                conn.remote_ip
            """.split()
    }
   
    for tp, names in basic_key_types:
        for key in names:
            assert_(type(environ[key]) is tp, "Invalid value type.")

    if len(environ["wsgi.script_name"]):
        assert_(environ["wsgi.script_name"][0] == b("/"),
                    "wsgi.script_name doesn't start with '/'")
Exemple #12
0
 def handle(self, app):
     try:
         response = app(self.environ)
         if response is None:
             return False
         (status, headers, body) = response
         self.respond(status, headers, body)
     except:
         if self.started:
             raise
         tb = traceback.format_exc().encode("ascii", "replace")
         headers = [
             (b("Content-Type"), b("text/plain")),
             (b("Content-Length"), b(str(len(tb))))
         ]
         self.respond(500, headers, [tb])
     return True
Exemple #13
0
    def parse(self, unreader):
        buf = BufferIO()

        self._get_data(unreader, buf, stop=True)
        
        # Request line
        idx = buf.getvalue().find(b("\r\n"))
        while idx < 0:
            self._get_data(unreader, buf)
            idx = buf.getvalue().find(b("\r\n"))
        self.parse_request_line(buf.getvalue()[:idx])
        rest = buf.getvalue()[idx+2:] # Skip \r\n
        buf.truncate(0)
        buf.seek(0)
        buf.write(rest)
        
        # Headers
        idx = buf.getvalue().find(b("\r\n\r\n"))
        done = buf.getvalue()[:2] == b("\r\n")
        while idx < 0 and not done:
            self._get_data(unreader, buf)
            idx = buf.getvalue().find(b("\r\n\r\n"))
            done = buf.getvalue()[:2] == b("\r\n")
        if done:
            self.unreader.unread(buf.getvalue()[2:])
            return b("")
        self.headers = self.parse_headers(buf.getvalue()[:idx])

        ret = buf.getvalue()[idx+4:]
        buf.truncate(0)
        buf.seek(0)
        return ret
Exemple #14
0
    def parse(self, unreader):
        buf = BufferIO()

        self._get_data(unreader, buf, stop=True)

        # Request line
        idx = buf.getvalue().find(b("\r\n"))
        while idx < 0:
            self._get_data(unreader, buf)
            idx = buf.getvalue().find(b("\r\n"))
        self.parse_request_line(buf.getvalue()[:idx])
        rest = buf.getvalue()[idx + 2:]  # Skip \r\n
        buf.truncate(0)
        buf.seek(0)
        buf.write(rest)

        # Headers
        idx = buf.getvalue().find(b("\r\n\r\n"))
        done = buf.getvalue()[:2] == b("\r\n")
        while idx < 0 and not done:
            self._get_data(unreader, buf)
            idx = buf.getvalue().find(b("\r\n\r\n"))
            done = buf.getvalue()[:2] == b("\r\n")
        if done:
            self.unreader.unread(buf.getvalue()[2:])
            return b("")
        self.headers = self.parse_headers(buf.getvalue()[:idx])

        ret = buf.getvalue()[idx + 4:]
        buf.truncate(0)
        buf.seek(0)
        return ret
Exemple #15
0
def check_status(status):
    assert_(type(status) == type(b("")), "Status must be a bytes object.")
    status_code = status.split(None, 1)[0]
    assert_(len(status) == 3, "Status code must be three digits.")
    assert_(int(status) >= 100, "Status code must be >= 100")
    assert_(int(parts[0]) > 100, "Invalid status respones.")
    assert_(len(parts) == 2, "No status message provided.")
    assert_(len(status.split(None, 1)) == 2,
                "The status should include a status message.")
Exemple #16
0
    def set_body_reader(self):
        chunked = False
        clength = 0

        for (name, value) in self.headers:
            if name.lower() == b("content-length"):
                try:
                    clength = int(value)
                except ValueError:
                    clength = 0
            elif name.lower() == b("transfer-encoding"):
                chunked = value.lower() == b("chunked")
            elif name.lower() == b("sec-websocket-key1"):
                clength = 8

        if chunked:
            self.body = Body(ChunkedReader(self.unreader, self))
        else:
            self.body = Body(LengthReader(self.unreader, clength))
Exemple #17
0
    def set_body_reader(self):
        chunked = False
        clength = 0

        for (name, value) in self.headers:
            if name.lower() == b("content-length"):
                try:
                    clength = int(value)
                except ValueError:
                    clength = 0
            elif name.lower() == b("transfer-encoding"):
                chunked = value.lower() == b("chunked")
            elif name.lower() == b("sec-websocket-key1"):
                clength = 8

        if chunked:
            self.body = Body(ChunkedReader(self.unreader, self))
        else:
            self.body = Body(LengthReader(self.unreader, clength))
Exemple #18
0
def parse(value):
    ret = {
        "scheme": None,
        "userinfo": None,
        "host": None,
        "port": None,
        "path": None,
        "query": None,
        "fragment": None
    }
    if value == b("*"):
        ret["path"] = b("*")
        return ret
    for pat in patterns:
        match = pat.match(value)
        if match:
            ret.update(match.groupdict())
            return ret
    raise ValueError(b("Invalid HTTP URI: ") + value)
Exemple #19
0
def parse(value):
    ret = {
        "scheme": None,
        "userinfo": None,
        "host": None,
        "port": None,
        "path": None,
        "query": None,
        "fragment": None
    }
    if value == b("*"):
        ret["path"] = b("*")
        return ret
    for pat in patterns:
        match = pat.match(value)
        if match:
            ret.update(match.groupdict())
            return ret
    raise ValueError(b("Invalid HTTP URI: ") + value)
Exemple #20
0
 def render(self):
     ret = [b("(") + self.name]
     for i, n in enumerate(self.nodes):
         ret.append(b("(?:") + n.render() + b(")"))
         if i + 1 < len(self.nodes):
             ret.append(b("|"))
     ret.append(b(")"))
     return b("").join(ret)
Exemple #21
0
 def render(self):
     ret = [b("(") + self.name]
     for i, n in enumerate(self.nodes):
         ret.append(b("(?:") + n.render() + b(")"))
         if i+1 < len(self.nodes):
             ret.append(b("|"))
     ret.append(b(")"))
     return b("").join(ret)
Exemple #22
0
    def __init__(self, unreader):
        self.unreader = unreader

        self.methre = re.compile(b("[A-Z0-9$-_.]{3,20}"))
        self.versre = re.compile(b("HTTP/(\d+).(\d+)"))
        self.hdrre = re.compile(b("[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]"))

        self.method = None
        self.uri = None
        self.scheme = None
        self.userinfo = None
        self.host = None
        self.port = b("80")
        self.path = None
        self.query = None
        self.fragment = None
        self.version = None
        self.headers = []
        self.trailers = []
        self.body = None

        unused = self.parse(self.unreader)
        self.unreader.unread(unused)
        self.set_body_reader()
Exemple #23
0
    def __init__(self, unreader):
        self.unreader = unreader

        self.methre = re.compile(b("[A-Z0-9$-_.]{3,20}"))
        self.versre = re.compile(b("HTTP/(\d+).(\d+)"))
        self.hdrre = re.compile(b("[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]"))

        self.method = None
        self.uri = None
        self.scheme = None
        self.userinfo = None
        self.host = None
        self.port = b("80")
        self.path = None
        self.query = None
        self.fragment = None
        self.version = None
        self.headers = []
        self.trailers = []
        self.body = None

        unused = self.parse(self.unreader)
        self.unreader.unread(unused)
        self.set_body_reader()
Exemple #24
0
 def render(self):
     ret = [b("(") + self.name]
     for n in self.nodes:
         ret.append(n.render())
     ret.append(b(")"))
     return b("").join(ret)
Exemple #25
0
 def render(self):
     return b("[") + self.bytes + b("]")
Exemple #26
0
 def __init__(self, bytes):
     self.bytes = b(bytes)
Exemple #27
0
 def __init__(self, name=None):
     if name is None:
         self.name = b("?:")
     else:
         self.name = b("?P<") + b(name) + b(">")
Exemple #28
0
 def render(self):
     return b("(") + self.name + self.node.render() + b(")?")
Exemple #29
0
 def render(self):
     ret = [b("(") + self.name]
     for n in self.nodes:
         ret.append(n.render())
     ret.append(b(")"))
     return b("").join(ret)
Exemple #30
0
 def __init__(self, bytes):
     self.bytes = b(bytes)
Exemple #31
0
 def __init__(self, byte):
     self.byte = b(byte)
Exemple #32
0
 def render(self):
     rep = b("(?:") + self.node.render() + b(")") + self.n
     return b("(") + self.name + rep + b(")")
Exemple #33
0
 def __init__(self, name=None):
     if name is None:
         self.name = b("?:")
     else:
         self.name = b("?P<") + b(name) + b(">")
Exemple #34
0
 def render(self):
     rep = b("(?:") + self.node.render() + b(")") + self.n
     return b("(") + self.name + rep + b(")")
Exemple #35
0
 def compile(self):
     return re.compile(b("^") + self.render() + b("$"))
Exemple #36
0
import re

from wsgiref2.util import b

BOOL_TYPE = type(True)
INT_TYPE = type(1)
BYTES_TYPE = type(b(""))
STRING_TYPE = type("")

HDR_NAME_RE = re.compile(b("[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]"))
HDR_VALUE_RE = re.compile(b("\n[^ \t]"))


def assert_(cond, *args):
    if not cond:
        raise AssertionError(*args)


def check_environ(environ):
    # Keys covered in specific validaotors:
    #   http.body, wsgi.errors, wsgi.upgrade, wsgi.upgraded

    assert_(envrion["wsgi.version"] == (2, 0), "Invalid wsgi version.")
    
    for key in environ.keys():
        assert_(type(key) is STRING_TYPE, "Invalid environ key type.")

    basic_key_types = {
        BOOL_TYPE: """
                wsgi.multithread wsg.multiprocess
Exemple #37
0
 def __init__(self, byte):
     self.byte = b(byte)
Exemple #38
0
 def compile(self):
     return re.compile(b("^") + self.render() + b("$"))
Exemple #39
0
 def app(self, environ):
     status = 200
     body = pprint.pformat(environ).encode('latin-1')
     headers = [(b("Content-Type"), b("text/plain")),
                (b("Content-Length"), b(str(len(body))))]
     return status, headers, [body]
Exemple #40
0
 def render(self):
     return b("(") + self.name + self.node.render() + b(")?")
Exemple #41
0
 def render(self):
     return b("[") + self.bytes + b("]")