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")
40 self.sk = sk.dup().makefile("rwb")
41 self.handler = handler
45 head = readhead(self.sk)
46 self.handler(head, self.sk)
50 def handlescgi(sk, handler):
51 t = reqthread(sk, handler)
54 def servescgi(socket, handler):
56 nsk, addr = socket.accept()
58 handlescgi(nsk, handler)
62 def decodehead(head, coding):
63 return {k.decode(coding): v.decode(coding) for k, v in head.items()}
65 def wrapwsgi(handler):
68 env = decodehead(head, "utf-8")
69 env["wsgi.uri_encoding"] = "utf-8"
71 env = decodehead(head, "latin-1")
72 env["wsgi.uri_encoding"] = "latin-1"
73 env["wsgi.version"] = 1, 0
74 if "HTTP_X_ASH_PROTOCOL" in env:
75 env["wsgi.url_scheme"] = env["HTTP_X_ASH_PROTOCOL"]
77 env["wsgi.url_scheme"] = "https"
79 env["wsgi.url_scheme"] = "http"
80 env["wsgi.input"] = sk
81 env["wsgi.errors"] = sys.stderr
82 env["wsgi.multithread"] = True
83 env["wsgi.multiprocess"] = False
84 env["wsgi.run_once"] = False
90 if isinstance(thing, collections.ByteString):
93 return str(thing).encode("latin-1")
98 raise Exception("Trying to write data before starting response.")
99 status, headers = resp
102 buf += b"Status: " + recode(status) + b"\n"
103 for nm, val in headers:
104 buf += recode(nm) + b": " + recode(val) + b"\n"
121 def startreq(status, headers, exc_info = None):
123 if exc_info: # Interesting, this...
128 exc_info = None # CPython GC bug?
130 raise Exception("Can only start responding once.")
131 resp[:] = status, headers
134 respiter = handler(env, startreq)
137 for data in respiter:
144 if hasattr(respiter, "close"):