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
|
#!/usr/bin/env python2
import os, mimetypes, json, cgi, recode, time, urllib, events, threading
from config import config
from directory import Directory, File
class Application(object):
# Application handlers
def files(self, environ, start_response, path):
full_path = os.path.join(config.get('music_root'), *path[1:])
rel_path = os.path.join(*path[1:] or '.')
if os.path.isdir(full_path):
start_response('200 OK', [('Content-Type', 'text/html; charset=UTF-8')])
return (str(x) for x in Directory(rel_path).listdir())
else:
args = cgi.FieldStorage(environ = environ)
decoder = args.getvalue('decoder') if 'decoder' in args else None
encoder = args.getvalue('encoder') if 'encoder' in args else None
if decoder and encoder:
cache_file = File(rel_path).get_cache_file()
return File(cache_file, True).send(environ, start_response)
else:
return File(rel_path).send(environ, start_response)
def static(self, environ, start_response, path):
filename = os.path.join('static', *path[1:])
if not os.access(filename, os.F_OK) or '..' in path:
start_response('404 Not Found', [])
return []
mime = mimetypes.guess_type(filename, strict = False)[0] or 'application/octet-stream'
start_response('200 OK', [('Content-Type', mime)])
return open(filename, 'rb')
# JSON handlers
def json_list(self, environ, start_response, path):
args = cgi.FieldStorage(environ = environ)
directory = args.getvalue('directory') if 'directory' in args else '/'
d = Directory(directory)
contents = d.listdir()
start_response('200 OK', [('Content-Type', 'text/plain')])
s = json.dumps([x.json() for x in contents])
return s
def json_cache(self, environ, start_response, path):
args = cgi.FieldStorage(environ = environ)
path = args.getvalue('path') if 'path' in args else None
decoder = args.getvalue('decoder') if 'decoder' in args else None
encoder = args.getvalue('encoder') if 'encoder' in args else None
f = File(path)
t = threading.Thread(target = f.recode, args = (decoder, encoder))
t.start()
start_response('200 OK', [('Content-Type', 'text/plain')])
return []
def json_is_cached(self, environ, start_response, path):
args = cgi.FieldStorage(environ = environ)
path = args.getvalue('path') if 'path' in args else None
cache_file = os.path.join(config.get('cache_dir'), path)
cache_file = os.path.splitext(cache_file)[0] + '.mp3'
start_response('200 OK', [('Content-Type', 'text/plain')])
return json.dumps(os.path.exists(cache_file))
handlers = {
'files': files,
'static': static,
'list': json_list,
'cache': json_cache,
'is_cached': json_is_cached,
'events': events.EventSubscriber,
}
# WSGI handler
def __call__(self, environ, start_response):
path = urllib.unquote(environ['PATH_INFO'])
path = path.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', [('Content-Type', 'text/plain')])
return [str(path)]
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()
|