This repository has been archived by the owner on Oct 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.py
121 lines (97 loc) · 3.38 KB
/
server.py
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A server for uploading and analyzing audio with Amen
"""
import re
import json
import hashlib
from tempfile import NamedTemporaryFile
from redis import Redis
from rq import Queue
import tornado.ioloop
import tornado.web
from tornado import gen
from queue_functions import do_work
from queue_functions import make_audio
# Change this to the uploader of your choice!
from uploaders.s3 import get_url
from uploaders.s3 import upload
def handle_post(q, files, upload_function, analysis_function):
"""
Helper function for the main POST / analysis request, for easier testing.
It returns a string of a JSON object with the URLs for the uploaded audio and analysis.
Parameters
---------
q : rq.Queue
The main queue object to send the analysis work to.
files : dictionary
A dictionary representing the files section of the HTTP POST request.
upload_function : function
A function to upload the results of the analysis to a cloud server.
This is passed on to the queue processing function.
analysis_function : function
A function to do the analysis. In practice this is always queue_functions.make_audio.
The overly verbose API is to make testing easier.
Like `upload_function`, this function is passed on to the queue.
Returns
------
String
"""
file_body = files['file'][0]['body']
target_filename = files['file'][0]['filename']
target_filename = re.sub(r'[^\w\.]', '', target_filename)
hash_object = hashlib.md5(target_filename.encode())
audio_filename = hash_object.hexdigest() + "-" + target_filename
analysis_filename = audio_filename + '.analysis.json'
audio_url = get_url(audio_filename)
analysis_url = get_url(analysis_filename)
f = NamedTemporaryFile(delete=False)
filepath = f.name
f.write(file_body)
f.close()
q.enqueue(do_work, (filepath, audio_filename, analysis_filename, upload_function, analysis_function))
res = {'audio': audio_url, 'analysis': analysis_url}
return json.dumps(res)
class MainHandler(tornado.web.RequestHandler):
def set_default_headers(self):
"""
Tornado function to allow web-wide access to the server, via the Access-Control header.
"""
self.set_header("Access-Control-Allow-Origin", "*")
@gen.coroutine
def get(self):
"""
Tornado handler for GET requests.
"""
self.write("Hello, world")
@gen.coroutine
def post(self):
"""
Tornado handler for POST requests. Creates the queue, and then calls `handle_post`
"""
# We should clearly not create the Q here, but here we are
q = Queue(connection=Redis())
res = handle_post(q, self.request.files, upload, make_audio)
self.write(res)
def make_app(path):
"""
Helper function to create the server.
Parameters
---------
Path : str
Determines what the base path (/, /amen, /wombat, etc) of the server is.
Returns
------
Tornado.web.Application
"""
return tornado.web.Application([
(path, MainHandler),
])
if __name__ == "__main__":
# Debug settings for running locally with docker! Update as needed for your docker and nginx config.
path = '/'
port = 80
app = make_app(path)
app.listen(port)
tornado.ioloop.IOLoop.current().start()