Dolda2000 GitWeb
/
ashd.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
python: Initial porting of the Python code to Python 3.
[ashd.git]
/
python
/
ashd
/
scgi.py
diff --git
a/python/ashd/scgi.py
b/python/ashd/scgi.py
index
9357e9d
..
a06267f
100644
(file)
--- a/
python/ashd/scgi.py
+++ b/
python/ashd/scgi.py
@@
-1,28
+1,32
@@
-import sys
+import sys
, collections
import threading
class protoerr(Exception):
pass
import threading
class protoerr(Exception):
pass
+class closed(IOError):
+ def __init__(self):
+ super(closed, self).__init__("The client has closed the connection.")
+
def readns(sk):
hln = 0
while True:
c = sk.read(1)
def readns(sk):
hln = 0
while True:
c = sk.read(1)
- if c == ':':
+ if c ==
b
':':
break
break
- elif c >=
'0' or c <=
'9':
- hln = (hln * 10) + (ord(c) - ord('0'))
+ elif c >=
b'0' or c <= b
'9':
+ hln = (hln * 10) + (ord(c) - ord(
b
'0'))
else:
else:
- raise protoerr
, "Invalid netstring length byte: " + c
+ raise protoerr
("Invalid netstring length byte: " + c)
ret = sk.read(hln)
ret = sk.read(hln)
- if sk.read(1) != ',':
- raise protoerr
, "Non-terminated netstring"
+ if sk.read(1) !=
b
',':
+ raise protoerr
("Non-terminated netstring")
return ret
def readhead(sk):
return ret
def readhead(sk):
- parts = readns(sk).split('\0')[:-1]
+ parts = readns(sk).split(
b
'\0')[:-1]
if len(parts) % 2 != 0:
if len(parts) % 2 != 0:
- raise protoerr
, "Malformed headers"
+ raise protoerr
("Malformed headers")
ret = {}
i = 0
while i < len(parts):
ret = {}
i = 0
while i < len(parts):
@@
-33,7
+37,7
@@
def readhead(sk):
class reqthread(threading.Thread):
def __init__(self, sk, handler):
super(reqthread, self).__init__(name = "SCGI request handler")
class reqthread(threading.Thread):
def __init__(self, sk, handler):
super(reqthread, self).__init__(name = "SCGI request handler")
- self.sk = sk.dup().makefile("r
+
")
+ self.sk = sk.dup().makefile("r
wb
")
self.handler = handler
def run(self):
self.handler = handler
def run(self):
@@
-55,9
+59,17
@@
def servescgi(socket, handler):
finally:
nsk.close()
finally:
nsk.close()
+def decodehead(head, coding):
+ return {k.decode(coding): v.decode(coding) for k, v in head.items()}
+
def wrapwsgi(handler):
def handle(head, sk):
def wrapwsgi(handler):
def handle(head, sk):
- env = dict(head)
+ try:
+ env = decodehead(head, "utf-8")
+ env["wsgi.uri_encoding"] = "utf-8"
+ except UnicodeError:
+ env = decodehead(head, "latin-1")
+ env["wsgi.uri_encoding"] = "latin-1"
env["wsgi.version"] = 1, 0
if "HTTP_X_ASH_PROTOCOL" in env:
env["wsgi.url_scheme"] = env["HTTP_X_ASH_PROTOCOL"]
env["wsgi.version"] = 1, 0
if "HTTP_X_ASH_PROTOCOL" in env:
env["wsgi.url_scheme"] = env["HTTP_X_ASH_PROTOCOL"]
@@
-74,39
+86,60
@@
def wrapwsgi(handler):
resp = []
respsent = []
resp = []
respsent = []
- def write(data):
- if not data:
- return
+ def recode(thing):
+ if isinstance(thing, collections.ByteString):
+ return thing
+ else:
+ return str(thing).encode("latin-1")
+
+ def flushreq():
if not respsent:
if not resp:
if not respsent:
if not resp:
- raise Exception
, "Trying to write data before starting response."
+ raise Exception
("Trying to write data before starting response.")
status, headers = resp
respsent[:] = [True]
status, headers = resp
respsent[:] = [True]
- sk.write("Status: %s\n" % status)
+ buf = bytearray()
+ buf += b"Status: " + recode(status) + b"\n"
for nm, val in headers:
for nm, val in headers:
- sk.write("%s: %s\n" % (nm, val))
- sk.write("\n")
- sk.write(data)
- sk.flush()
+ buf += recode(nm) + b": " + recode(val) + b"\n"
+ buf += b"\n"
+ try:
+ sk.write(buf)
+ except IOError:
+ raise closed()
+
+ def write(data):
+ if not data:
+ return
+ flushreq()
+ try:
+ sk.write(data)
+ sk.flush()
+ except IOError:
+ raise closed()
def startreq(status, headers, exc_info = None):
if resp:
if exc_info: # Interesting, this...
try:
if respsent:
def startreq(status, headers, exc_info = None):
if resp:
if exc_info: # Interesting, this...
try:
if respsent:
- raise exc_info[
0], exc_info[1], exc_info[2
]
+ raise exc_info[
1
]
finally:
exc_info = None # CPython GC bug?
else:
finally:
exc_info = None # CPython GC bug?
else:
- raise Exception
, "Can only start responding once."
+ raise Exception
("Can only start responding once.")
resp[:] = status, headers
return write
respiter = handler(env, startreq)
try:
resp[:] = status, headers
return write
respiter = handler(env, startreq)
try:
- for data in respiter:
- write(data)
- write("")
+ try:
+ for data in respiter:
+ write(data)
+ if resp:
+ flushreq()
+ except closed:
+ pass
finally:
if hasattr(respiter, "close"):
respiter.close()
finally:
if hasattr(respiter, "close"):
respiter.close()