1 #!/usr/bin/python
2 import cgi
3 import mimetypes
4 import os
5 import posixpath
6 import re
7 
8 from mako import exceptions
9 from mako.lookup import TemplateLookup
10 
11 root = "./"
12 port = 8000
13 
14 lookup = TemplateLookup(
15     directories=[root + "templates", root + "htdocs"],
16     filesystem_checks=True,
17     module_directory="./modules",
18     # even better would be to use 'charset' in start_response
19     output_encoding="ascii",
20     encoding_errors="replace",
21 )
22 
23 
24 def serve(environ, start_response):
25     """serves requests using the WSGI callable interface."""
26     fieldstorage = cgi.FieldStorage(
27         fp=environ["wsgi.input"], environ=environ, keep_blank_values=True
28     )
29     d = dict([(k, getfield(fieldstorage[k])) for k in fieldstorage])
30 
31     uri = environ.get("PATH_INFO", "/")
32     if not uri:
33         uri = "/index.html"
34     else:
35         uri = re.sub(r"^/$", "/index.html", uri)
36 
37     if re.match(r".*\.html$", uri):
38         try:
39             template = lookup.get_template(uri)
40         except exceptions.TopLevelLookupException:
41             start_response("404 Not Found", [])
42             return [str.encode("Cant find template '%s'" % uri)]
43 
44         start_response("200 OK", [("Content-type", "text/html")])
45 
46         try:
47             return [template.render(**d)]
48         except:
49             return [exceptions.html_error_template().render()]
50     else:
51         u = re.sub(r"^\/+", "", uri)
52         filename = os.path.join(root, u)
53         if os.path.isfile(filename):
54             start_response("200 OK", [("Content-type", guess_type(uri))])
55             return [open(filename, "rb").read()]
56         else:
57             start_response("404 Not Found", [])
58             return [str.encode("File not found: '%s'" % filename)]
59 
60 
61 def getfield(f):
62     """convert values from cgi.Field objects to plain values."""
63     if isinstance(f, list):
64         return [getfield(x) for x in f]
65     else:
66         return f.value
67 
68 
69 extensions_map = mimetypes.types_map.copy()
70 
71 
72 def guess_type(path):
73     """return a mimetype for the given path based on file extension."""
74     base, ext = posixpath.splitext(path)
75     if ext in extensions_map:
76         return extensions_map[ext]
77     ext = ext.lower()
78     if ext in extensions_map:
79         return extensions_map[ext]
80     else:
81         return "text/html"
82 
83 
84 if __name__ == "__main__":
85     import wsgiref.simple_server
86 
87     server = wsgiref.simple_server.make_server("", port, serve)
88     print("Server listening on port %d" % port)
89     server.serve_forever()
90