7f1066a58b701c71faab412294d5c1b3c6b857f6
[wrw.git] / wrw / dispatch.py
1 import sys, traceback
2 from . import env, req, proto
3
4 __all__ = ["restart"]
5
6 class restart(Exception):
7     def handle(self, req):
8         pass
9
10 def mangle(result):
11     try:
12         iter(result)
13     except TypeError:
14         pass
15     else:
16         return result
17     return [str(result)]
18
19 def defaulterror(req, excinfo):
20     from . import resp
21     traceback.print_exception(*excinfo)
22     sys.stderr.flush()
23     raise resp.httperror(500)
24
25 def wraphandler(handler, excinfo):
26     def wrapped(req):
27         return handler(req, excinfo)
28     wrapped.__wrapped__ = handler
29     return wrapped
30
31 errorhandler = env.var(defaulterror)
32
33 def handle(req, startreq, handler):
34     eh = errorhandler.val
35     try:
36         resp = [""]
37         while True:
38             try:
39                 resp = handler(req)
40                 break
41             except restart as i:
42                 handler = i.handle
43             except Exception as i:
44                 if eh is None:
45                     raise
46                 handler = wraphandler(eh, sys.exc_info())
47                 eh = None
48         req.commit(startreq)
49         return resp
50     finally:
51         req.cleanup()
52
53 def handleenv(env, startreq, handler):
54     if not "HTTP_HOST" in env:
55         return proto.simpleerror(env, startreq, 400, "Bad Request", "Request must include Host header.")
56     r = req.origrequest(env)
57     return handle(r, startreq, handler)
58
59 def exterror(env, startreq):
60     def handler(req):
61         import resp
62         code = 404
63         if "Response-Code" in req.ihead:
64             try:
65                 code = int(req.ihead["Response-Code"])
66             except ValueError:
67                 pass
68         raise resp.httperror(code)
69     return handleenv(env, startreq, handler)