htparser: Add a `Server' header if none previously present.
[ashd.git] / python / ashd / wsgidir.py
1 import os, threading, types
2 import wsgiutil
3
4 class cachedmod:
5     def __init__(self, mod, mtime):
6         self.lock = threading.Lock()
7         self.mod = mod
8         self.mtime = mtime
9
10 exts = {}
11 modcache = {}
12 cachelock = threading.Lock()
13
14 def mangle(path):
15     ret = ""
16     for c in path:
17         if c.isalnum():
18             ret += c
19         else:
20             ret += "_"
21     return ret
22
23 def getmod(path):
24     sb = os.stat(path)
25     cachelock.acquire()
26     try:
27         if path in modcache:
28             entry = modcache[path]
29             if sb.st_mtime <= entry.mtime:
30                 return entry
31         
32         f = open(path)
33         try:
34             text = f.read()
35         finally:
36             f.close()
37         code = compile(text, path, "exec")
38         mod = types.ModuleType(mangle(path))
39         mod.__file__ = path
40         exec code in mod.__dict__
41         entry = cachedmod(mod, sb.st_mtime)
42         modcache[path] = entry
43         return entry
44     finally:
45         cachelock.release()
46
47 def chain(path, env, startreq):
48     mod = getmod(path)
49     entry = None
50     if mod is not None:
51         mod.lock.acquire()
52         try:
53             if hasattr(mod, "entry"):
54                 entry = mod.entry
55             else:
56                 if hasattr(mod.mod, "wmain"):
57                     entry = mod.mod.wmain([])
58                 elif hasattr(mod.mod, "application"):
59                     entry = mod.mod.application
60                 mod.entry = entry
61         finally:
62             mod.lock.release()
63     if entry is not None:
64         return entry(env, startreq)
65     return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "Invalid WSGI handler.")
66 exts["wsgi"] = chain
67
68 def application(env, startreq):
69     if not "SCRIPT_FILENAME" in env:
70         return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
71     path = env["SCRIPT_FILENAME"]
72     base = os.path.basename(path)
73     p = base.rfind('.')
74     if p < 0 or not os.access(path, os.R_OK):
75         return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
76     ext = base[p + 1:]
77     if not ext in exts:
78         return wsgiutil.simpleerror(env, startreq, 500, "Internal Error", "The server is erroneously configured.")
79     return(exts[ext](path, env, startreq))
80
81 def wmain(argv):
82     return application