1 import sys, collections
4 class protoerr(Exception):
9 super(closed, self).__init__("The client has closed the connection.")
17 elif c >= b'0' or c <= b'9':
18 hln = (hln * 10) + (ord(c) - ord(b'0'))
20 raise protoerr("Invalid netstring length byte: " + c)
22 if sk.read(1) != b',':
23 raise protoerr("Non-terminated netstring")
27 parts = readns(sk).split(b'\0')[:-1]
28 if len(parts) % 2 != 0:
29 raise protoerr("Malformed headers")
33 ret[parts[i]] = parts[i + 1]
37 class reqthread(threading.Thread):
38 def __init__(self, sk, handler):
39 super(reqthread, self).__init__(name = "SCGI request handler")
41 self.sk = self.bsk.makefile("rwb")
42 self.handler = handler
46 head = readhead(self.sk)
47 self.handler(head, self.sk)
52 def handlescgi(sk, handler):
53 t = reqthread(sk, handler)
56 def servescgi(socket, handler):
58 nsk, addr = socket.accept()
60 handlescgi(nsk, handler)
64 def decodehead(head, coding):
65 return {k.decode(coding): v.decode(coding) for k, v in head.items()}
67 def wrapwsgi(handler):
70 env = decodehead(head, "utf-8")
71 env["wsgi.uri_encoding"] = "utf-8"
73 env = decodehead(head, "latin-1")
74 env["wsgi.uri_encoding"] = "latin-1"
75 env["wsgi.version"] = 1, 0
76 if "HTTP_X_ASH_PROTOCOL" in env:
77 env["wsgi.url_scheme"] = env["HTTP_X_ASH_PROTOCOL"]
79 env["wsgi.url_scheme"] = "https"
81 env["wsgi.url_scheme"] = "http"
82 env["wsgi.input"] = sk
83 env["wsgi.errors"] = sys.stderr
84 env["wsgi.multithread"] = True
85 env["wsgi.multiprocess"] = False
86 env["wsgi.run_once"] = False
92 if isinstance(thing, collections.ByteString):
95 return str(thing).encode("latin-1")
100 raise Exception("Trying to write data before starting response.")
101 status, headers = resp
104 buf += b"Status: " + recode(status) + b"\n"
105 for nm, val in headers:
106 buf += recode(nm) + b": " + recode(val) + b"\n"
123 def startreq(status, headers, exc_info = None):
125 if exc_info: # Interesting, this...
130 exc_info = None # CPython GC bug?
132 raise Exception("Can only start responding once.")
133 resp[:] = status, headers
136 respiter = handler(env, startreq)
139 for data in respiter:
146 if hasattr(respiter, "close"):