Пассажир + фляга и экранирование URL

Я пишу приложение на Flask, которое будет развернуто на Dreamhost через Passenger. У меня есть такая настройка, что я могу работать локально, используя ./run.py (env - это мой виртуальный каталог):

#!env/bin/python

from my_website import app
app.run(debug=True)

и развертывание в Dreamhost работает со следующими passenger_wsgi.py:

#!env/bin/python
import sys, os
INTERP = os.path.join(os.getcwd(), 'env', 'bin', 'python')
if sys.executable != INTERP:
    os.execl(INTERP, INTERP, *sys.argv)
sys.path.append(os.getcwd())
from my_website import app as application

Большинство вещей работает нормально. Однако я столкнулся с проблемой, когда Passenger не декодирует PATH_INFO URL-адреса, как должен делать WSGI. Например, у меня настроен маршрут (в my_website/__init__.py:

app.add_url_rule('/example/<key>', 'examplepage', examplepage.show_page)

Для страниц с простыми ключами это прекрасно работает как в Passenger, так и в локальном режиме. Однако, если я перейду, например, на example.com/example/test%20key, в моей локальной системе разработки examplepage.show_page будет вызван с key='test key', как и ожидалось, но через Passenger он будет вызван с key='test%20key'.

Похоже, что встроенный HTTP-сервер Flask декодирует URL-адрес PATH_INFO еще до того, как он попадет в парсер URL-адресов Flask, поэтому в результате %2F символов также преждевременно декодируются; поскольку Flask ожидает, что URL-адрес уже будет декодирован URL-адресом в этот момент, он не выполняет декодирование URL-адресов отдельных проанализированных компонентов пути. Однако Passenger + WSGI сохраняет PATH_INFO, и, таким образом, символы в кодировке URL остаются в кодировке URL (что, по-видимому, является ошибкой в ​​реализации WSGI Passenger).

Итак, каков самый простой способ согласовать поведение пассажира и ./run.py?


person fluffy    schedule 01.08.2015    source источник


Ответы (1)


Кажется, это работает хорошо (в passenger_wsgi.py), хотя может быть что-то не так:

from my_website import app

# hackish way to apply WSGI's url decoding in Passenger
import urllib2
def application(environ, start_response):
    environ["PATH_INFO"] = urllib2.unquote(environ["PATH_INFO"])
    return app(environ, start_response)

Одна заметная проблема заключается в том, что это означает, что %2f больше не обрабатывается правильно, хотя это могло быть через Passenger; однако для его правильной обработки потребовалось бы внести в Flask огромные изменения, которые были бы несовместимы с подавляющим большинством стеков WSGI.

person fluffy    schedule 01.08.2015
comment
Согласно github.com/mitsuhiko/flask/issues/900, очевидно, проблема в том, что WSGI указывает, что URL-адрес PATH_INFO должен быть предварительно расшифрован, а Passenger просто не соблюдает спецификацию WSGI. - person fluffy; 01.08.2015