Welcome! Log In Create A New Profile

Advanced

Re: client_max_body_size inside if

November 12, 2019 09:52AM
On Mon, Nov 11, 2019 at 05:23:55PM +0300, Михаил Монашёв wrote:
> Здравствуйте.
>
> Оказалось, что client_max_body_size не работает внутри if-а .
>
> Хотел ограничивать размер GET- и POST-запросов, не ограничивая размер
> PUT-запросов, поступающих с доверенных ip. Конфиг планировался
> примерно такой:
>
> server {
> listen 80;
> server_name xxxxx;
>
> expires 1y;
>
> location / {
> root /xxxx/yyyyy;
>
> if ($request_method == PUT ) {
> client_max_body_size 0; # disable request size checks
> }
>
> client_body_temp_path /xxxx/webdav-tmp;
>
> dav_methods PUT DELETE MKCOL COPY MOVE;
> create_full_put_path on;
> dav_access user:rw group:rw all:r;
>
> limit_except GET {
> allow 127.0.0.0/8;
> allow 10.0.0.0/8;
>
> deny all;
> }
> }
> }
>
> Добавить NGX_HTTP_LIF_CONF в ngx_http_core_module.c не проблема. Но
> если есть возможность менять client_max_body_size внутри if-ов в самом
> nginx-е, было бы здорово. Если против этого, конечно же, нет никаких
> возражений.

Всё не так просто.

Сейчас для обычного (не-chunked) тела запроса проверка на данное ограничение
встроена в фазу FIND_CONFIG, обработчик которой вызывается при исходном выборе
location'а, а также каждый раз, когда location выбирается при помощи директивы
rewrite.

Можно передвинуть проверку на ограничение в фазу POST_REWRITE. От этого
становится чуть лучше, и client_max_body_size начинает работать внутри "if"
(добавления только NGX_HTTP_LIF_CONF недостаточно), но ограничение всё равно
будет проверяться по числу выборов новых location'ов, и в целом идея работать
не будет, т.к. фактически будет срабатывать наименьшее из ограничений:

location /1 {
client_max_body_size 8;
rewrite /1 /2;
}

location /2 {
client_max_body_size 9;
rewrite /2 /3;
}

location /3 {
client_max_body_size 10;
}
}

Кроме того, фазы POST_REWRITE может и не быть, так что туда нельзя.
Аналогично, не подходит и фаза POST_ACCESS (её также может не быть).
Остаётся убрать это в CONTENT-фазу, но насколько это хорошее изменение,
я пока не до конца понимаю.

Proof of concept патч:

# HG changeset patch
# User Ruslan Ermilov <ru@nginx.com>
# Date 1573570198 -10800
# Tue Nov 12 17:49:58 2019 +0300
# Node ID f50e2acbb576cbd699307a647da3e4ec2dbe5b48
# Parent 1ab95c51955e9c9fc9954b4d43d287c87a97fe0e
Enabled client_max_body_size inside "if".

diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -343,7 +343,8 @@ static ngx_command_t ngx_http_core_comm
NULL },

{ ngx_string("client_max_body_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+ |NGX_CONF_TAKE1,
ngx_conf_set_off_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, client_max_body_size),
@@ -961,25 +962,6 @@ ngx_http_core_find_config_phase(ngx_http

ngx_http_update_location_config(r);

- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http cl:%O max:%O",
- r->headers_in.content_length_n, clcf->client_max_body_size);
-
- if (r->headers_in.content_length_n != -1
- && !r->discard_body
- && clcf->client_max_body_size
- && clcf->client_max_body_size < r->headers_in.content_length_n)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client intended to send too large body: %O bytes",
- r->headers_in.content_length_n);
-
- r->expect_tested = 1;
- (void) ngx_http_discard_request_body(r);
- ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
- return NGX_OK;
- }
-
if (rc == NGX_DONE) {
ngx_http_clear_location(r);

@@ -1160,9 +1142,31 @@ ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
- size_t root;
- ngx_int_t rc;
- ngx_str_t path;
+ size_t root;
+ ngx_int_t rc;
+ ngx_str_t path;
+ ngx_http_core_loc_conf_t *clcf;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http cl:%O max:%O",
+ r->headers_in.content_length_n, clcf->client_max_body_size);
+
+ if (r->headers_in.content_length_n != -1
+ && !r->discard_body
+ && clcf->client_max_body_size
+ && clcf->client_max_body_size < r->headers_in.content_length_n)
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "client intended to send too large body: %O bytes",
+ r->headers_in.content_length_n);
+
+ r->expect_tested = 1;
+ (void) ngx_http_discard_request_body(r);
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
+ return NGX_OK;
+ }

if (r->content_handler) {
r->write_event_handler = ngx_http_request_empty_handler;
_______________________________________________
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru
Subject Author Posted

client_max_body_size inside if

Михаил Монашёв November 11, 2019 09:26AM

Re: client_max_body_size inside if

fox November 11, 2019 09:34AM

Re: client_max_body_size inside if

Михаил Монашёв November 11, 2019 09:38AM

Re: client_max_body_size inside if

ru@nginx.com November 12, 2019 09:52AM

Re: client_max_body_size inside if

Михаил Монашёв November 12, 2019 01:26PM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 154
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready