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