0
|
1 #!/usr/bin/env python
|
|
2
|
|
3 """
|
|
4 WSGI app for FileServer
|
|
5
|
|
6 Reference:
|
|
7 - http://docs.webob.org/en/latest/file-example.html
|
|
8 """
|
|
9
|
|
10 import mimetypes
|
|
11 import os
|
|
12 from webob import Request, Response, exc
|
|
13
|
|
14 def get_mimetype(filename):
|
|
15 type, encoding = mimetypes.guess_type(filename)
|
|
16 # We'll ignore encoding, even though we shouldn't really
|
|
17 return type or 'application/octet-stream'
|
|
18
|
|
19 def file_response(filename):
|
|
20 res = Response(content_type=get_mimetype(filename))
|
|
21 res.body = open(filename, 'rb').read()
|
|
22 return res
|
|
23
|
|
24 class FileApp(object):
|
|
25 """
|
|
26 serve static files
|
|
27 """
|
|
28
|
|
29 def __init__(self, filename):
|
|
30 self.filename = filename
|
|
31
|
|
32 def __call__(self, environ, start_response):
|
|
33 res = file_response(self.filename)
|
|
34 return res(environ, start_response)
|
|
35
|
|
36 class DirectoryServer(object):
|
|
37
|
|
38 def __init__(self, directory):
|
|
39 assert os.path.exists(directory), "'%s' does not exist" % directory
|
|
40 assert os.path.isdir(directory), "'%s' is not a directory" % directory
|
|
41 self.directory = directory
|
|
42
|
|
43 @staticmethod
|
|
44 def normpath(path):
|
|
45 return os.path.normcase(os.path.abspath(path))
|
|
46
|
|
47 def __call__(self, environ, start_response):
|
|
48 request = Request(environ)
|
|
49 # TODO method_not_allowed: Allow: GET, HEAD
|
|
50 path_info = request.path_info
|
|
51 if not path_info:
|
|
52 pass # self.add slash
|
|
53 full = self.normpath(os.path.join(self.directory, path_info.strip('/')))
|
|
54 if not full.startswith(self.directory):
|
|
55 # Out of bounds
|
|
56 return exc.HTTPNotFound()(environ, start_response)
|
|
57 if not os.path.exists(full):
|
|
58 return exc.HTTPNotFound()(environ, start_response)
|
|
59
|
|
60 if os.path.isdir(full):
|
|
61 # serve directory index
|
|
62 if not path_info.endswith('/'):
|
|
63 return self.add_slash(environ, start_response)
|
|
64 index = self.index(full)
|
|
65 response_headers = [('Content-Type', 'text/html'),
|
|
66 ('Content-Length', str(len(index)))]
|
|
67 response = Response(index, content_type='text/html')
|
|
68 return response(environ, start_response)
|
|
69
|
|
70 # serve file
|
|
71 if path_info.endswith('/'):
|
|
72 # we create the `full` filename above by stripping off
|
|
73 # '/' from both sides; so we correct here
|
|
74 return exc.HTTPNotFound()(environ, start_response)
|
|
75 response = file_response(full)
|
|
76 return response(environ, start_response)
|
|
77
|
|
78 if __name__ == '__main__':
|
|
79 from wsgiref import simple_server
|
|
80 app = Handler()
|
|
81 server = simple_server.make_server(host='0.0.0.0', port=8080, app=app)
|
|
82 server.serve_forever()
|