-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplaylistserver.py
More file actions
130 lines (101 loc) · 3.58 KB
/
playlistserver.py
File metadata and controls
130 lines (101 loc) · 3.58 KB
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
130
#!/usr/bin/env python
""" Simple server to serve music folders as playlists.
When run from directory, it will serve its content as
playlist, showing only files with appropriate extensions.
Most code "borrowed" from SimpleHTTPServer.
"""
__author__ = "Matej Kollar"
__contact__ = "xkolla06@stud.fit.vutbr.cz"
__version__ = "1.0"
__date__ = "2013. 10. 20."
__license__ = "GPLv3"
__credits__ = [__author__]
__maintainer__ = __author__
__status__ = "Working"
import SimpleHTTPServer
import BaseHTTPServer
import SocketServer
import os
import urllib
import sys
import errno
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
# class PlaylistHTTPServer(BaseHTTPServer.HTTPServer):
class PlaylistHTTPServer(
SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
"""Server to serve directory as a playlist"""
ok_errnos = [
errno.ECONNRESET,
errno.EPIPE]
def handle_error(self, request, client_address):
"""Handle an error gracefully.
Ignore early connection close on client side,
otherwise print traceback and continue.
"""
err = sys.exc_info()[1]
self.close_request(request)
if isinstance(err, IOError) and err.errno in self.ok_errnos:
return
# New style `super` does not work here :-(
return BaseHTTPServer.HTTPServer.handle_error(
self, request, client_address)
class PlaylistHTTPHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""Handler to serve directory as a playlist"""
server_version = "PlaylistServer/" + __version__
ALLOWED_EXTENSIONS = ["mp3", "flac"]
def check_path(self, path):
"""Is path allowed?"""
return path.rsplit('.', 1)[-1] in self.ALLOWED_EXTENSIONS
def send_head(self):
path = self.translate_path(self.path)
if self.check_path(path) or os.path.isdir(path):
return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
self.send_error(404, "Not found")
return None
def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html).
Return value is either a file object, or None (indicating an
error). In either case, the headers are sent, making the
interface the same as for send_head().
"""
try:
files = filter(self.check_path, os.listdir(path))
except os.error:
self.send_error(404, "Not found")
return None
files.sort(key=lambda a: a.lower())
resp = StringIO()
for name in files:
fullname = os.path.join(path, name)
if os.path.isdir(fullname):
continue
resp.write('%s\n' % urllib.quote(name))
length = resp.tell()
resp.seek(0)
self.send_response(200)
encoding = sys.getfilesystemencoding()
self.send_header("Content-type", "text/plain; charset=%s" % encoding)
self.send_header("Content-Length", str(length))
self.end_headers()
return resp
def main():
"""Main. Takes one argument on command line: port to serve on."""
if sys.argv[1:]:
port = int(sys.argv[1])
else:
port = 8000
server_address = ('', port)
server = PlaylistHTTPServer(
server_address, PlaylistHTTPHandler, "HTTP/1.1")
print "Serving playlists on port", server_address[1], "..."
try:
server.serve_forever()
except KeyboardInterrupt:
print "Shutting down..."
server.shutdown()
if __name__ == '__main__':
main()