Welcome! Log In Create A New Profile

Advanced

Re: PUT и POST module handler

Maxim Dounin
October 14, 2015 09:00AM
Hello!

On Tue, Oct 13, 2015 at 02:13:04AM -0400, rba wrote:

> Здравствуйте.
> Почитал форум, посмотрел исходники и сообразил до некоторого порядка
> обработки данных запросов. Остались некоторые вопросы. Понимаю что ответы
> можно найти в исходниках(echo,dav и.т.д.) но силы и терпение на исходе
> поэтому прошу помощи.

Я бы не рекомендовал ничего искать в исходниках "echo", там у
автора подход "если оно работает, то и хорошо". Имеет смысл для
начала смотреть в исходники самого nginx'а и стандартных модулей.

[...]

> static void
> ngx_http_rbsample_debug(ngx_http_request_t *r, u_char *buffer, int nbytes)
> {//Это заглушка, в будущем некоторая неблокирующая функция отправляющая в
> специфичный бэкенд
> /**********************************************************
> 1. ngx_log_debug1 вроде выводит buffer и без завершения \0 или стоит
> дополнять конструкцией типа
> u_char *p;
> p = ngx_pnalloc(r->pool, nbytes+1);
> p = ngx_cpymem(p, buffer, nbytes+1);
> p[nbytes+1]='\0';
> ...и выводить p
> **********************************************************/
> ngx_log_debug1(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "RBSAMPLE 2.
> put/post: \"%s\"", buffer);

Стоит переписать на использование %*s или ngx_str_t + %V.
Формат %s подразумевает null-терминированную строку, и без
завершающего \0 оно рано или поздно развалится.

Очевидно, что просто %s не может работать даже теоретически -
длину строки вы не передаёте, и если она не null-терминирована, то
узнать, где она кончается, невозможно.

> }
>
> static void
> ngx_http_rbsample_post_handler(ngx_http_request_t *r)
> {
> size_t len;
> ngx_buf_t *buf;
> ngx_chain_t *cl;
>
> if (r->request_body == NULL && r->request_body->temp_file == NULL) {
> ngx_log_debug(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "RBSAMPLE
> 999. error put/post!!!!");
> ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
> return;
> }
> ngx_log_debug(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "RBSAMPLE 1.
> put/post!!!!");
>
> /**********************************************************
> 2. Не блокернёт ли следующий цикл воркер непрерывным чтением большого
> буфера, если ngx_http_rbsample_debug(сейчас заглушка) не блокирующая,
> или желательно после каждого cl->next как-то отдавать управление?

Пока вы не вернёте управление - воркер, по очевидным причинам,
больше ничего делать не может. Соответственно, если процесс
обработки может занимать заметное время - это придётся как-то
решать (или мириться).

> 3. Будет ли порядок обработки тем же, если nginx положит тело запроса в
> файл?

В этом случае тела запроса, очевидно, не будет в памяти. В
r->request_body->bufs будет лежать соответствующий буфер в файле.
Придётся научиться с ними работать.

> 4. Как можно отдать управление воркеру(что вернуть из текущего хэндлера) и
> отложить обработку ngx_http_rbsample_debug, не трогая буфер, не завершая
> запрос и не передавая обработку остальным хэндлерам в текущем запросе?

Понятия "остальных хендлеров" в случае чтения тела запроса не
существует, единственный обработчик - ваш. При этом завершение
запроса возможно только в том случае, если вы сами позовёте
ngx_http_finalize_request(). Пока не позвали - вы отвечаете за
дальнейшую обработку запроса.

Например, в этот момент можно начать что-то делать в другом
соединении, и возобновлять работу запроса по событиям от него.
Так, в частности, работает модуль upstream, который используют
proxy/fastcgi/memcached.

> 4.1. Чтобы в новом витке воркера вернуться к текущему запросу и cl, нужно
> его(cl) выносить в глобальное пространство(есть ли какие-то особенности в
> nginx?) или есть иные принятые в nginx способы?

Для сохранения данных модулей в nginx'е есть контексты модулей,
см. ngx_http_set_ctx().

[...]

> static ngx_int_t
> ngx_http_rbsample_handler(ngx_http_request_t *r)
> {
> ngx_int_t rc;
> ngx_log_debug(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "rbsample 0.
> ngx_http_rbsample_handler!");
>
> if(r->method == NGX_HTTP_PUT || r->method == NGX_HTTP_POST) {
> r->request_body_in_file_only = 0;
> r->request_body_in_single_buf=1;
>
> /*********************************************************
> 5. Корректно ли так подключать обработчик POST/PUT в таком контексте, или
> лучше его делать фазовым?
> **********************************************************/

Корректно.

Делать обработчик фазовым нужно в том случае, если вам нужно
обрабатывать не все запросы и сосуществовать с другими модулями,
как это делает модуль DAV. Если такой задачи нет и обработке
подлежат все запросы - проще и правильнее сделать handler на
уровне location.

--
Maxim Dounin
http://nginx.org/

_______________________________________________
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru
Subject Author Posted

PUT и POST module handler

rba October 13, 2015 02:13AM

Re: PUT и POST module handler

rba October 14, 2015 03:34AM

Re: PUT и POST module handler

rba October 14, 2015 04:55AM

Re: PUT и POST module handler

Maxim Dounin October 14, 2015 09:00AM

Re: PUT и POST module handler

rba October 19, 2015 03:19AM

Re: PUT и POST module handler

Maxim Dounin October 19, 2015 11:14AM

Re: PUT и POST module handler

rba December 29, 2015 02:57AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 120
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 500 on July 15, 2024
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready