This is how I have my tornado web server currently defined:
application = tornado.web.Application([
tornado.web.url(r"/server", MainHandler),
tornado.web.url(r"/(.*)", tornado.web.StaticFileHandler, { "path": scriptpath, "default_filename": "index.html" }),
])
index.html is the start page of a web based gui. It will communicate with the backend server through http:///server and the requests by the gui to the server are handled by the MainHandler function.
The directory structure looks like:
root_directory/
server.py
fileiwanttodownload.tar.gz
index.html
I would like to be able to type into the browser:
http:///data/fileiwanttodownload.tar.gz
and have the file delivered to me as a regular file download.
What I have tried to do is:
application = tornado.web.Application([
tornado.web.url(r"/server", MainHandler),
tornado.web.url(r"/data", tornado.web.StaticFileHandler, { "path": scriptpath } ),
tornado.web.url(r"/(.*)", tornado.web.StaticFileHandler, { "path": scriptpath, "default_filename": "index.html" }),
])
But this is not working for reasons that are probably obvious to those who know the answer.
The only clue I have is the following error message:
Uncaught exception GET /data (192.168.4.168)
HTTPServerRequest(protocol='http', host='192.168.4.195:8888', method='GET', uri='/data', version='HTTP/1.1', remote_ip='192.168.4.168', headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9', 'Host': '192.168.4.195:8888', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Connection': 'keep-alive', 'Accept-Language': 'en-us'})
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/tornado/web.py", line 1445, in _execute
result = yield result
File "/usr/local/lib/python3.4/dist-packages/tornado/gen.py", line 1008, in run
value = future.result()
File "/usr/local/lib/python3.4/dist-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
File "/usr/local/lib/python3.4/dist-packages/tornado/gen.py", line 267, in wrapper
result = func(*args, **kwargs)
TypeError: get() missing 1 required positional argument: 'path'
scriptpath
you haven't shown, is probably wrong. In path
you should provide root dir to the files, in URI matcher capture only the file or so. Simple example:
import tornado.ioloop
import tornado.web
import os
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
script_path = os.path.dirname(__file__)
return tornado.web.Application([
(r"/", MainHandler),
(r"/data/(.*)", tornado.web.StaticFileHandler, {"path": script_path}),
# ^ we capture only this part
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
As you can run it works, but it is recommended to store static/data files in separate directory, because it is possible to download everything from the app root dir, including python one.
So put your downloadable file e.g. in data subdirectory and then
script_path = os.path.join(os.path.dirname(__file__), 'data')
More info about StaticFileHandler.
edit
The error you are getting is because in your code /data
route has StaticFileHandler, but nothing is captured ()
from requested path.