Mercurial > hg > nginx
view src/event/ngx_event_timer.c @ 9260:ac5635650bc6
Request body: handling of body after unbuffered reading.
As long as unbuffered reading of the request body was used, and an attempt
to read the request body is made again, such as when redirecting the request
to an error page, the request body is now cleared to make sure it can be
used safely.
Further, the r->reading_body flag, if it is still set, is cleared (along with
disabling keepalive and enabling lingering close), so the code which uses
the request body, such as when proxying, is not confused and doesn't try
to use "Transfer-Encoding: chunked".
Note that this change makes the workaround for HTTP/2 issues with unbuffered
proxying and error pages, as introduced in 7561:9f1f9d6e056a, ineffective
(since r->reading_body now cleared along with r->reading_body_no_buffering).
Though the workaround is anyway not needed after 7924:d9e009b39596, hence
it is removed.
This makes it safer to use complex processing of error pages with unbuffered
proxying.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sat, 27 Apr 2024 18:22:07 +0300 |
parents | 0c5e84096d99 |
children |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> ngx_rbtree_t ngx_event_timer_rbtree; static ngx_rbtree_node_t ngx_event_timer_sentinel; /* * the event timer rbtree may contain the duplicate keys, however, * it should not be a problem, because we use the rbtree to find * a minimum timer value only */ ngx_int_t ngx_event_timer_init(ngx_log_t *log) { ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel, ngx_rbtree_insert_timer_value); return NGX_OK; } ngx_msec_t ngx_event_find_timer(void) { ngx_msec_int_t timer; ngx_rbtree_node_t *node, *root, *sentinel; if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) { return NGX_TIMER_INFINITE; } root = ngx_event_timer_rbtree.root; sentinel = ngx_event_timer_rbtree.sentinel; node = ngx_rbtree_min(root, sentinel); timer = (ngx_msec_int_t) (node->key - ngx_current_msec); return (ngx_msec_t) (timer > 0 ? timer : 0); } void ngx_event_expire_timers(void) { ngx_event_t *ev; ngx_rbtree_node_t *node, *root, *sentinel; sentinel = ngx_event_timer_rbtree.sentinel; for ( ;; ) { root = ngx_event_timer_rbtree.root; if (root == sentinel) { return; } node = ngx_rbtree_min(root, sentinel); /* node->key > ngx_current_msec */ if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) { return; } ev = ngx_rbtree_data(node, ngx_event_t, timer); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "event timer del: %d: %M", ngx_event_ident(ev->data), ev->timer.key); ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); #if (NGX_DEBUG) ev->timer.left = NULL; ev->timer.right = NULL; ev->timer.parent = NULL; #endif ev->timer_set = 0; ev->timedout = 1; ev->handler(ev); } } ngx_int_t ngx_event_no_timers_left(void) { ngx_event_t *ev; ngx_rbtree_node_t *node, *root, *sentinel; sentinel = ngx_event_timer_rbtree.sentinel; root = ngx_event_timer_rbtree.root; if (root == sentinel) { return NGX_OK; } for (node = ngx_rbtree_min(root, sentinel); node; node = ngx_rbtree_next(&ngx_event_timer_rbtree, node)) { ev = ngx_rbtree_data(node, ngx_event_t, timer); if (!ev->cancelable) { return NGX_AGAIN; } } /* only cancelable timers left */ return NGX_OK; }