2014-01-21 5 views
7

Я разрабатываю простое веб-приложение с торнадо. Он обслуживает некоторые динамические файлы и некоторые статические. Динамические проблемы не являются проблемой, но мне трудно обслуживать статический файл. То, что я хочу сделать, это обслуживать файл /path/to/foo.json при доступе к URL-адресу /foo.json.Как Tornado может обслуживать один статический файл в произвольном месте?

Обратите внимание, что /path/to/foo.json находится вне корня документа. В Apache я бы просто создал псевдоним. С Торнадо у меня есть:

app = tornado.web.Application([ 
    (r'/dynamic\.html', MyService, dict(param = 12345)), 
    (r'/(foo\.json)', tornado.web.StaticFileHandler, {'path': '/path/to/foo.json'}) 
    ]) 

Я добавил регулярное выражение оператора группы (), чтобы удовлетворить Торнадо, который выбросил исключение иначе. Но теперь, когда я обращаюсь к /foo.json, я получаю 404: Файл не найден.

Тесты показывают, что Tornado пытается использовать путь, предоставленный в качестве корневого каталога, к которому он добавляет foo.json, подразумевая, что мой файл можно найти, если он находится в /path/to/foo.json/foo.json. Закрыть, но не совсем.

Я предполагаю, что я мог бы сократить свой путь до простого «/ path/to», который вызовет выборку /path/to/foo.json по URL-адресу /foo.json, но это заставляет меня использовать тот же имя в URL-адресе, как в файловой системе. Как я могу просто сделать простой, произвольный URL-адрес для сопоставления файлов?

Я сделал некоторые исследования по этому вопросу, читая документацию для tornado.web.Application и tornado.web.StaticFilehandler, а также некоторые otherSOquestions. Ничто не является моим прецедентом.

+0

Итак, произвольное сопоставление файлов, что вы хотите, это сопоставить, скажем, URL 'yourdomain.com/path/to/foo.json' с' yourfilesystem/path/to/bar.json'? Я думаю, вы должны включить это в свой вопрос (т. Е. Использовать другое имя в примере, не используя 'foo.json' как в URL-адрес, так и в файловой системе) – justhalf

+0

Я упоминаю это в своем втором-последнем абзаце, @justhalf, но, возможно, это может быть яснее. –

+0

Да, я хочу включить то, что вы называете в своем втором последнем абзаце в вашем примере. Потому что ваш пример действительно не представляет собой ваш реальный вопрос. – justhalf

ответ

4

Что-то, как это должно работать:

import os 
import tornado.ioloop 
import tornado.web 


class MyFileHandler(tornado.web.StaticFileHandler): 
    def initialize(self, path): 
     self.dirname, self.filename = os.path.split(path) 
     super(MyFileHandler, self).initialize(self.dirname) 

    def get(self, path=None, include_body=True): 
     # Ignore 'path'. 
     super(MyFileHandler, self).get(self.filename, include_body) 

app = tornado.web.Application([ 
    (r'/foo\.json', MyFileHandler, {'path': '/path/to/foo.json'}) 
]) 

app.listen(8888) 
tornado.ioloop.IOLoop.current().start() 

URL, шаблон и имя файла не должно быть связано, вы могли бы сделать это, и это будет работать так же хорошо:

app = tornado.web.Application([ 
    (r'/jesse\.txt', MyFileHandler, {'path': '/path/to/foo.json'}) 
]) 
+1

Обратите внимание, что подклассификация StaticFileHandler может быть деликатной, и лучше оставить 'get()' самостоятельно. Вместо этого метод class_ get_absolute_path' является лучшим методом для переопределения здесь (http://www.tornadoweb.org/en/stable/web.html#tornado.web.StaticFileHandler.get_absolute_path) –

+0

Мне нравится этот подход, и это хорошо работает для меня. Но меня заинтриговал подход переопределения 'get_absolute_path'. @BenDarnell, можете ли вы привести пример? –

+1

Это не проверено, но оно иллюстрирует общую идею: https://gist.github.com/bdarnell/8553378 –

5

StaticFileHandler получает это имя файла из группы захвата регулярных выражений и имя каталога из аргумента пути. Она будет работать, если вы используете /path/to/ в качестве пути:

(r'/(foo\.json)', tornado.web.StaticFileHandler, {'path': '/path/to/'}) 

StaticFileHandler предназначен для случаев, когда URL-адреса и имена совпадают; если вы не можете организовать доступ к этому файлу на диске под тем же именем, который вы хотите ему обслуживать, так как вам придется использовать собственный обработчик.

11

StaticFileHandler два аргумента, так что если вы хотите один URL (/foo.json), который будет отображаться на вашем пути к файлу вы можете использовать:

app = tornado.web.Application([ 
(r'/foo.json()', tornado.web.StaticFileHandler, {'path': '/path/to/foo.json'}) 
]) 

Регулярное выражение будет соответствовать /foo.json и отправить пустой захват group (), что приведет к тому, что путь к файлу будет использоваться как есть. Когда группа захвата не пуста, /path/to/foo.json будет рассматриваться как каталог /path/to/foo.json/, и обработчик попытается сопоставить все, что находится в группе захвата, с именем файла в этом каталоге.

+0

Спасибо, Марк. Мне нравится простота этого подхода. +1. –

Смежные вопросы