Re: webdav в rest на nginx: upload, подзапрос, замена параметров запроса и ответа
Maxim Dounin
mdounin на mdounin.ru
Пн Окт 4 15:16:30 MSD 2010
Hello!
On Mon, Oct 04, 2010 at 12:44:58PM +0400, Vasiliy Fedorov wrote:
> Привет.
>
> Есть задача по организации upload & download больших файлов (несколько
> Гб) авторизованных пользователей.
> Внешнее API, допустим, WebDAV. У бэкенда какое-то REST API и находятся
> они на разных машинах.
> Легкие запросы к WebDAV можно отдавать обрабатывать еще одному бэкенду
> (список файлов директории, свойства файлов, удаление файла) -- пусть к
> REST ходит сам, но запросы на upload и download файлов гонять через
> этот бэкенд не хочется, хочется напрямую отдавать в REST.
>
> Пытаюсь понять подходит ли Nginx для такой задачи, и что хочется чтобы
> умел proxy:
> 1. Прочитать заголовки запроса, не читая контент.
> 2. Сходить по какому-то URL с теми же заголовками, проверить что
> запрос пропустить можно, ответ на этот запрос можно выдать в любом
> устраивающем Nginx формате (чем сходить? у Nginx есть только SSI, но
> они включаются только в ответе (?))
В зависимости от конкретной задачи - можно либо сделать через
X-Accel-Redirect, либо взять какой-нибудь из модулей:
eval (http://grid.net.ru/nginx/eval.en.html), auth request
(http://mdounin.ru/hg/ngx_http_auth_request_module/).
> 3. Если нельзя -- ругнуться пользователю, если можно -- поменять
> request: method, uri, заголовки* -- и проксировать дальше.
Менять методы и заголовки можно в коробке, про uri даже и не
говорю.
proxy_set_header
Документация есть тут:
http://sysoev.ru/nginx/docs/http/ngx_http_proxy_module.html#proxy_set_header
proxy_method
Официально недокументировано, описание есть в вики:
http://wiki.nginx.org/NginxHttpProxyModule#proxy_method
Ну и до кучи там же в wiki:
proxy_pass_request_body
proxy_pass_request_headers
proxy_set_body
> (Проксировать дальше не считывая весь контент запроса, как я понимаю,
> нельзя:
> "Note that when using the HTTP Proxy Module (or even when using
> FastCGI), the entire client request will be buffered in nginx before
> being passed on to the backend proxied servers." (
> http://wiki.nginx.org/HttpProxyModule#Synopsis )
> То есть upload больших файлов работать будет плохо.
Да.
> *: X-Accel-Redirect тут подходит плохо, хотя и используют для похожих
> вещей: http://kovyrin.net/2010/07/24/nginx-fu-x-accel-redirect-remote/
X-Accel-Redirect подходит, но требует некоторой аккуратности в
написании конфигов.
> То есть проблемы 3:
> 1. Upload всего файла.
> 2. Авторизация через другой сервер.
> 3. Замена параметров запроса в зависимости от подзапроса на лету.
>
> Идеи:
> 1. Непонятно почему "я не дожен хотеть" прямого проксирования запросов
> на upload, но у Lighttpd поведение такое же. То есть, казалось бы,
> логично прочитать заголовки запроса, разобраться с ними, записать в
> выходной сокет новые заголовки, вызвать splice (man splice).
В большинстве случаев пропускать ещё не полученный запрос на
бекенд - излишняя трата ресурсов. Кроме того, при таком подходе
пропадает возможность перепослать запрос на другой бекенд, если с
первым что-то случилось и он запрос недочитал.
Сделать подобный вариант обработки для больших постов безусловно
имеет смысл, но это a) требует времени и b) нужно далеко не всегда.
> 2. Авторизация через другой сервер:
> -- можно попробовать запрос направить на статический файлик с SSI
> инструкциями, первой инструкцией сходить авторизоваться, в зависимости
> от значения ответа вызывать разные SSI (не авторизован -- ошибка,
> авторизован -- вызвать url)
Нет, так работать не будет. Статический файл выкинет тело
запроса.
> -- куда при этом денется контент запроса? отправится и в первый
> SSI и во второй? Или ни в один из SSI?
> -- какими будут заголовки ответа? (Например, Content-Type для
> скачивания видео).
> -- можно пробовать использовать embedded Perl, но он не умеет
> отправлять неблокирующие http-запросы. Embedded Lua, кстати, говорит
> что умеет ( http://github.com/chaoslawful/lua-nginx-module ) -- но
> модуль слишком новый, непонятно как с ним связываться.
> 3. Теоретически менять заголовки и метод можно, есть набор директив,
> но как соотнести с другими вариантами -- непонятно, разработчик
> lua-модуля пишет что изменять параметры запроса lua-модуль еще не
> умеет, хотя и хочет.
>
> Возможно ли то что хочется вообще сделать через Nginx? Какие-то еще
> есть варианты? Что-то другое, не Nginx, более приспособлено для
> решения таких задач?
>
> P.S.: Директива proxy_pass_request_body есть в документации на
> английском (http://wiki.nginx.org/HttpProxyModule#proxy_pass_request_body),
> нет в документации на русском
> (http://sysoev.ru/nginx/docs/http/ngx_http_proxy_module.html) и нет
> слов о ее отмене в changes (http://sysoev.ru/nginx/changes.html)
Это недокументированная директива.
Maxim Dounin
Подробная информация о списке рассылки nginx-ru