1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#!/usr/bin/env python2
import db, os, json, mimetypes, datetime
from config import config
class JSONApplication(object):
def list(self, environ, start_response, path):
root_id = int(path[1]) if len(path[1]) else 0
session = db.Session()
try:
if root_id > 0:
directory = db.Directory.get_by_id(session, root_id)
else:
directory = db.Directory.get(session, config.get('music_root'))
directories = directory.children
tracks = directory.tracks
contents = json.dumps([x.dict() for x in directories] +
[x.dict() for x in tracks])
finally:
session.close()
start_response('200 OK', [('Content-Type', 'application/json'), ('Content-Length', str(len(contents)))])
return [contents]
handlers = {
'list': list,
}
def __call__(self, environ, start_response, path):
module = path[0]
if module in self.handlers:
return self.handlers[module](self, environ, start_response, path)
class Application(object):
rfc1123_format = '%a, %d %b %Y %H:%M:%S +0000'
def __init__(self):
self.jsonapp = JSONApplication()
def json(self, environ, start_response, path):
path.pop(0)
return self.jsonapp(environ, start_response, path)
def _serve_path(self, environ, start_response, filename):
if not os.path.exists(filename) or '..' in filename.split(os.path.sep):
start_response('404 Not Found', [])
return []
do_range = 'HTTP_RANGE' in environ
if do_range:
file_range = environ['HTTP_RANGE'].split('bytes=')[1]
mime = mimetypes.guess_type(filename, strict = False)[0] or 'application/octet-stream'
last_modified = datetime.datetime.fromtimestamp(os.path.getmtime(filename)).strftime(self.rfc1123_format)
# Range handling
if do_range:
start, end = [int(x or 0) for x in file_range.split('-')]
size = os.path.getsize(filename)
if end == 0:
end = size-1
write_out = start_response('206 Partial Content', [('Content-Type', mime),
('Content-Range', 'bytes {start}-{end}/{size}'.format(start = start, end = end, size = size)),
('Content-Length', str(end - start + 1)), ('Last-Modified', last_modified)])
f = open(filename, 'rb')
f.seek(start)
remaining = end-start+1
s = f.read(min(remaining, 1024))
while s:
write_out(s)
remaining -= len(s)
s = f.read(min(remaining, 1024))
return []
start_response('200 OK', [('Content-Type', mime), ('Content-Length', str(os.path.getsize(filename))),
('Last-Modified', last_modified)])
return open(filename, 'rb')
def static(self, environ, start_response, path):
filename = os.path.join('static', *path[1:])
return self._serve_path(environ, start_response, filename)
def track(self, environ, start_response, path):
track = int(path[1])
session = db.Session()
try:
track = db.Track.get_by_id(session, track)
filename = track.get_path()
except db.NoResultFound:
start_response('404 Not Found', [])
return []
finally:
session.close()
return self._serve_path(environ, start_response, filename)
handlers = {
'json': json,
'static': static,
'file': file,
'track': track,
}
def __call__(self, environ, start_response):
path = environ['PATH_INFO'].split('/')[1:]
module = path[0] or None
if not module:
module = 'static'
path = ['static', 'index.html']
if module in self.handlers:
return self.handlers[module](self, environ, start_response, path)
start_response('404 Not Found', [])
return []
if __name__ == '__main__':
import sys
if len(sys.argv) == 3:
from flup.server.fcgi import WSGIServer
WSGIServer(Application(), bindAddress = (sys.argv[1], int(sys.argv[2]))).run()
else:
from wsgiref.simple_server import make_server, WSGIServer
# enable IPv6
WSGIServer.address_family |= 10
httpd = make_server('', 8000, Application())
httpd.serve_forever()
|