1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_http.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevstatic void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
14e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
15e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
16e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
17e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
18e18a033bSKonstantin Ananyev    ngx_buf_t *b);
19e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_test_expect(ngx_http_request_t *r);
20e18a033bSKonstantin Ananyev
21e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_request_body_filter(ngx_http_request_t *r,
22e18a033bSKonstantin Ananyev    ngx_chain_t *in);
23e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_request_body_length_filter(ngx_http_request_t *r,
24e18a033bSKonstantin Ananyev    ngx_chain_t *in);
25e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_http_request_body_chunked_filter(ngx_http_request_t *r,
26e18a033bSKonstantin Ananyev    ngx_chain_t *in);
27e18a033bSKonstantin Ananyev
28e18a033bSKonstantin Ananyev
29e18a033bSKonstantin Ananyevngx_int_t
30e18a033bSKonstantin Ananyevngx_http_read_client_request_body(ngx_http_request_t *r,
31e18a033bSKonstantin Ananyev    ngx_http_client_body_handler_pt post_handler)
32e18a033bSKonstantin Ananyev{
33e18a033bSKonstantin Ananyev    size_t                     preread;
34e18a033bSKonstantin Ananyev    ssize_t                    size;
35e18a033bSKonstantin Ananyev    ngx_int_t                  rc;
36e18a033bSKonstantin Ananyev    ngx_buf_t                 *b;
37e18a033bSKonstantin Ananyev    ngx_chain_t                out;
38e18a033bSKonstantin Ananyev    ngx_http_request_body_t   *rb;
39e18a033bSKonstantin Ananyev    ngx_http_core_loc_conf_t  *clcf;
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev    r->main->count++;
42e18a033bSKonstantin Ananyev
43e18a033bSKonstantin Ananyev    if (r != r->main || r->request_body || r->discard_body) {
44e18a033bSKonstantin Ananyev        r->request_body_no_buffering = 0;
45e18a033bSKonstantin Ananyev        post_handler(r);
46e18a033bSKonstantin Ananyev        return NGX_OK;
47e18a033bSKonstantin Ananyev    }
48e18a033bSKonstantin Ananyev
49e18a033bSKonstantin Ananyev#if (NGX_HTTP_V2)
50e18a033bSKonstantin Ananyev    if (r->stream) {
51e18a033bSKonstantin Ananyev        rc = ngx_http_v2_read_request_body(r, post_handler);
52e18a033bSKonstantin Ananyev        goto done;
53e18a033bSKonstantin Ananyev    }
54e18a033bSKonstantin Ananyev#endif
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyev    if (ngx_http_test_expect(r) != NGX_OK) {
57e18a033bSKonstantin Ananyev        rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
58e18a033bSKonstantin Ananyev        goto done;
59e18a033bSKonstantin Ananyev    }
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyev    rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
62e18a033bSKonstantin Ananyev    if (rb == NULL) {
63e18a033bSKonstantin Ananyev        rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
64e18a033bSKonstantin Ananyev        goto done;
65e18a033bSKonstantin Ananyev    }
66e18a033bSKonstantin Ananyev
67e18a033bSKonstantin Ananyev    /*
68e18a033bSKonstantin Ananyev     * set by ngx_pcalloc():
69e18a033bSKonstantin Ananyev     *
70e18a033bSKonstantin Ananyev     *     rb->bufs = NULL;
71e18a033bSKonstantin Ananyev     *     rb->buf = NULL;
72e18a033bSKonstantin Ananyev     *     rb->free = NULL;
73e18a033bSKonstantin Ananyev     *     rb->busy = NULL;
74e18a033bSKonstantin Ananyev     *     rb->chunked = NULL;
75e18a033bSKonstantin Ananyev     */
76e18a033bSKonstantin Ananyev
77e18a033bSKonstantin Ananyev    rb->rest = -1;
78e18a033bSKonstantin Ananyev    rb->post_handler = post_handler;
79e18a033bSKonstantin Ananyev
80e18a033bSKonstantin Ananyev    r->request_body = rb;
81e18a033bSKonstantin Ananyev
82e18a033bSKonstantin Ananyev    if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
83e18a033bSKonstantin Ananyev        r->request_body_no_buffering = 0;
84e18a033bSKonstantin Ananyev        post_handler(r);
85e18a033bSKonstantin Ananyev        return NGX_OK;
86e18a033bSKonstantin Ananyev    }
87e18a033bSKonstantin Ananyev
88e18a033bSKonstantin Ananyev    preread = r->header_in->last - r->header_in->pos;
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev    if (preread) {
91e18a033bSKonstantin Ananyev
92e18a033bSKonstantin Ananyev        /* there is the pre-read part of the request body */
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
95e18a033bSKonstantin Ananyev                       "http client request body preread %uz", preread);
96e18a033bSKonstantin Ananyev
97e18a033bSKonstantin Ananyev        out.buf = r->header_in;
98e18a033bSKonstantin Ananyev        out.next = NULL;
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev        rc = ngx_http_request_body_filter(r, &out);
101e18a033bSKonstantin Ananyev
102e18a033bSKonstantin Ananyev        if (rc != NGX_OK) {
103e18a033bSKonstantin Ananyev            goto done;
104e18a033bSKonstantin Ananyev        }
105e18a033bSKonstantin Ananyev
106e18a033bSKonstantin Ananyev        r->request_length += preread - (r->header_in->last - r->header_in->pos);
107e18a033bSKonstantin Ananyev
108e18a033bSKonstantin Ananyev        if (!r->headers_in.chunked
109e18a033bSKonstantin Ananyev            && rb->rest > 0
110e18a033bSKonstantin Ananyev            && rb->rest <= (off_t) (r->header_in->end - r->header_in->last))
111e18a033bSKonstantin Ananyev        {
112e18a033bSKonstantin Ananyev            /* the whole request body may be placed in r->header_in */
113e18a033bSKonstantin Ananyev
114e18a033bSKonstantin Ananyev            b = ngx_calloc_buf(r->pool);
115e18a033bSKonstantin Ananyev            if (b == NULL) {
116e18a033bSKonstantin Ananyev                rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
117e18a033bSKonstantin Ananyev                goto done;
118e18a033bSKonstantin Ananyev            }
119e18a033bSKonstantin Ananyev
120e18a033bSKonstantin Ananyev            b->temporary = 1;
121e18a033bSKonstantin Ananyev            b->start = r->header_in->pos;
122e18a033bSKonstantin Ananyev            b->pos = r->header_in->pos;
123e18a033bSKonstantin Ananyev            b->last = r->header_in->last;
124e18a033bSKonstantin Ananyev            b->end = r->header_in->end;
125e18a033bSKonstantin Ananyev
126e18a033bSKonstantin Ananyev            rb->buf = b;
127e18a033bSKonstantin Ananyev
128e18a033bSKonstantin Ananyev            r->read_event_handler = ngx_http_read_client_request_body_handler;
129e18a033bSKonstantin Ananyev            r->write_event_handler = ngx_http_request_empty_handler;
130e18a033bSKonstantin Ananyev
131e18a033bSKonstantin Ananyev            rc = ngx_http_do_read_client_request_body(r);
132e18a033bSKonstantin Ananyev            goto done;
133e18a033bSKonstantin Ananyev        }
134e18a033bSKonstantin Ananyev
135e18a033bSKonstantin Ananyev    } else {
136e18a033bSKonstantin Ananyev        /* set rb->rest */
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev        if (ngx_http_request_body_filter(r, NULL) != NGX_OK) {
139e18a033bSKonstantin Ananyev            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
140e18a033bSKonstantin Ananyev            goto done;
141e18a033bSKonstantin Ananyev        }
142e18a033bSKonstantin Ananyev    }
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev    if (rb->rest == 0) {
145e18a033bSKonstantin Ananyev        /* the whole request body was pre-read */
146e18a033bSKonstantin Ananyev        r->request_body_no_buffering = 0;
147e18a033bSKonstantin Ananyev        post_handler(r);
148e18a033bSKonstantin Ananyev        return NGX_OK;
149e18a033bSKonstantin Ananyev    }
150e18a033bSKonstantin Ananyev
151e18a033bSKonstantin Ananyev    if (rb->rest < 0) {
152e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
153e18a033bSKonstantin Ananyev                      "negative request body rest");
154e18a033bSKonstantin Ananyev        rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
155e18a033bSKonstantin Ananyev        goto done;
156e18a033bSKonstantin Ananyev    }
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
159e18a033bSKonstantin Ananyev
160e18a033bSKonstantin Ananyev    size = clcf->client_body_buffer_size;
161e18a033bSKonstantin Ananyev    size += size >> 2;
162e18a033bSKonstantin Ananyev
163e18a033bSKonstantin Ananyev    /* TODO: honor r->request_body_in_single_buf */
164e18a033bSKonstantin Ananyev
165e18a033bSKonstantin Ananyev    if (!r->headers_in.chunked && rb->rest < size) {
166e18a033bSKonstantin Ananyev        size = (ssize_t) rb->rest;
167e18a033bSKonstantin Ananyev
168e18a033bSKonstantin Ananyev        if (r->request_body_in_single_buf) {
169e18a033bSKonstantin Ananyev            size += preread;
170e18a033bSKonstantin Ananyev        }
171e18a033bSKonstantin Ananyev
172e18a033bSKonstantin Ananyev    } else {
173e18a033bSKonstantin Ananyev        size = clcf->client_body_buffer_size;
174e18a033bSKonstantin Ananyev    }
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev    rb->buf = ngx_create_temp_buf(r->pool, size);
177e18a033bSKonstantin Ananyev    if (rb->buf == NULL) {
178e18a033bSKonstantin Ananyev        rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
179e18a033bSKonstantin Ananyev        goto done;
180e18a033bSKonstantin Ananyev    }
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev    r->read_event_handler = ngx_http_read_client_request_body_handler;
183e18a033bSKonstantin Ananyev    r->write_event_handler = ngx_http_request_empty_handler;
184e18a033bSKonstantin Ananyev
185e18a033bSKonstantin Ananyev    rc = ngx_http_do_read_client_request_body(r);
186e18a033bSKonstantin Ananyev
187e18a033bSKonstantin Ananyevdone:
188e18a033bSKonstantin Ananyev
189e18a033bSKonstantin Ananyev    if (r->request_body_no_buffering
190e18a033bSKonstantin Ananyev        && (rc == NGX_OK || rc == NGX_AGAIN))
191e18a033bSKonstantin Ananyev    {
192e18a033bSKonstantin Ananyev        if (rc == NGX_OK) {
193e18a033bSKonstantin Ananyev            r->request_body_no_buffering = 0;
194e18a033bSKonstantin Ananyev
195e18a033bSKonstantin Ananyev        } else {
196e18a033bSKonstantin Ananyev            /* rc == NGX_AGAIN */
197e18a033bSKonstantin Ananyev            r->reading_body = 1;
198e18a033bSKonstantin Ananyev        }
199e18a033bSKonstantin Ananyev
200e18a033bSKonstantin Ananyev        r->read_event_handler = ngx_http_block_reading;
201e18a033bSKonstantin Ananyev        post_handler(r);
202e18a033bSKonstantin Ananyev    }
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
205e18a033bSKonstantin Ananyev        r->main->count--;
206e18a033bSKonstantin Ananyev    }
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev    return rc;
209e18a033bSKonstantin Ananyev}
210e18a033bSKonstantin Ananyev
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyevngx_int_t
213e18a033bSKonstantin Ananyevngx_http_read_unbuffered_request_body(ngx_http_request_t *r)
214e18a033bSKonstantin Ananyev{
215e18a033bSKonstantin Ananyev    ngx_int_t  rc;
216e18a033bSKonstantin Ananyev
217e18a033bSKonstantin Ananyev#if (NGX_HTTP_V2)
218e18a033bSKonstantin Ananyev    if (r->stream) {
219e18a033bSKonstantin Ananyev        rc = ngx_http_v2_read_unbuffered_request_body(r);
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyev        if (rc == NGX_OK) {
222e18a033bSKonstantin Ananyev            r->reading_body = 0;
223e18a033bSKonstantin Ananyev        }
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev        return rc;
226e18a033bSKonstantin Ananyev    }
227e18a033bSKonstantin Ananyev#endif
228e18a033bSKonstantin Ananyev
229e18a033bSKonstantin Ananyev    if (r->connection->read->timedout) {
230e18a033bSKonstantin Ananyev        r->connection->timedout = 1;
231e18a033bSKonstantin Ananyev        return NGX_HTTP_REQUEST_TIME_OUT;
232e18a033bSKonstantin Ananyev    }
233e18a033bSKonstantin Ananyev
234e18a033bSKonstantin Ananyev    rc = ngx_http_do_read_client_request_body(r);
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev    if (rc == NGX_OK) {
237e18a033bSKonstantin Ananyev        r->reading_body = 0;
238e18a033bSKonstantin Ananyev    }
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev    return rc;
241e18a033bSKonstantin Ananyev}
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyevstatic void
245e18a033bSKonstantin Ananyevngx_http_read_client_request_body_handler(ngx_http_request_t *r)
246e18a033bSKonstantin Ananyev{
247e18a033bSKonstantin Ananyev    ngx_int_t  rc;
248e18a033bSKonstantin Ananyev
249e18a033bSKonstantin Ananyev    if (r->connection->read->timedout) {
250e18a033bSKonstantin Ananyev        r->connection->timedout = 1;
251e18a033bSKonstantin Ananyev        ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
252e18a033bSKonstantin Ananyev        return;
253e18a033bSKonstantin Ananyev    }
254e18a033bSKonstantin Ananyev
255e18a033bSKonstantin Ananyev    rc = ngx_http_do_read_client_request_body(r);
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
258e18a033bSKonstantin Ananyev        ngx_http_finalize_request(r, rc);
259e18a033bSKonstantin Ananyev    }
260e18a033bSKonstantin Ananyev}
261e18a033bSKonstantin Ananyev
262e18a033bSKonstantin Ananyev
263e18a033bSKonstantin Ananyevstatic ngx_int_t
264e18a033bSKonstantin Ananyevngx_http_do_read_client_request_body(ngx_http_request_t *r)
265e18a033bSKonstantin Ananyev{
266e18a033bSKonstantin Ananyev    off_t                      rest;
267e18a033bSKonstantin Ananyev    size_t                     size;
268e18a033bSKonstantin Ananyev    ssize_t                    n;
269e18a033bSKonstantin Ananyev    ngx_int_t                  rc;
270e18a033bSKonstantin Ananyev    ngx_chain_t                out;
271e18a033bSKonstantin Ananyev    ngx_connection_t          *c;
272e18a033bSKonstantin Ananyev    ngx_http_request_body_t   *rb;
273e18a033bSKonstantin Ananyev    ngx_http_core_loc_conf_t  *clcf;
274e18a033bSKonstantin Ananyev
275e18a033bSKonstantin Ananyev    c = r->connection;
276e18a033bSKonstantin Ananyev    rb = r->request_body;
277e18a033bSKonstantin Ananyev
278e18a033bSKonstantin Ananyev    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
279e18a033bSKonstantin Ananyev                   "http read client request body");
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev    for ( ;; ) {
282e18a033bSKonstantin Ananyev        for ( ;; ) {
283e18a033bSKonstantin Ananyev            if (rb->buf->last == rb->buf->end) {
284e18a033bSKonstantin Ananyev
285e18a033bSKonstantin Ananyev                if (rb->buf->pos != rb->buf->last) {
286e18a033bSKonstantin Ananyev
287e18a033bSKonstantin Ananyev                    /* pass buffer to request body filter chain */
288e18a033bSKonstantin Ananyev
289e18a033bSKonstantin Ananyev                    out.buf = rb->buf;
290e18a033bSKonstantin Ananyev                    out.next = NULL;
291e18a033bSKonstantin Ananyev
292e18a033bSKonstantin Ananyev                    rc = ngx_http_request_body_filter(r, &out);
293e18a033bSKonstantin Ananyev
294e18a033bSKonstantin Ananyev                    if (rc != NGX_OK) {
295e18a033bSKonstantin Ananyev                        return rc;
296e18a033bSKonstantin Ananyev                    }
297e18a033bSKonstantin Ananyev
298e18a033bSKonstantin Ananyev                } else {
299e18a033bSKonstantin Ananyev
300e18a033bSKonstantin Ananyev                    /* update chains */
301e18a033bSKonstantin Ananyev
302e18a033bSKonstantin Ananyev                    rc = ngx_http_request_body_filter(r, NULL);
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev                    if (rc != NGX_OK) {
305e18a033bSKonstantin Ananyev                        return rc;
306e18a033bSKonstantin Ananyev                    }
307e18a033bSKonstantin Ananyev                }
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyev                if (rb->busy != NULL) {
310e18a033bSKonstantin Ananyev                    if (r->request_body_no_buffering) {
311e18a033bSKonstantin Ananyev                        if (c->read->timer_set) {
312e18a033bSKonstantin Ananyev                            ngx_del_timer(c->read);
313e18a033bSKonstantin Ananyev                        }
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyev                        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
316e18a033bSKonstantin Ananyev                            return NGX_HTTP_INTERNAL_SERVER_ERROR;
317e18a033bSKonstantin Ananyev                        }
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev                        return NGX_AGAIN;
320e18a033bSKonstantin Ananyev                    }
321e18a033bSKonstantin Ananyev
322e18a033bSKonstantin Ananyev                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
323e18a033bSKonstantin Ananyev                }
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev                rb->buf->pos = rb->buf->start;
326e18a033bSKonstantin Ananyev                rb->buf->last = rb->buf->start;
327e18a033bSKonstantin Ananyev            }
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev            size = rb->buf->end - rb->buf->last;
330e18a033bSKonstantin Ananyev            rest = rb->rest - (rb->buf->last - rb->buf->pos);
331e18a033bSKonstantin Ananyev
332e18a033bSKonstantin Ananyev            if ((off_t) size > rest) {
333e18a033bSKonstantin Ananyev                size = (size_t) rest;
334e18a033bSKonstantin Ananyev            }
335e18a033bSKonstantin Ananyev
336e18a033bSKonstantin Ananyev            n = c->recv(c, rb->buf->last, size);
337e18a033bSKonstantin Ananyev
338e18a033bSKonstantin Ananyev            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
339e18a033bSKonstantin Ananyev                           "http client request body recv %z", n);
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev            if (n == NGX_AGAIN) {
342e18a033bSKonstantin Ananyev                break;
343e18a033bSKonstantin Ananyev            }
344e18a033bSKonstantin Ananyev
345e18a033bSKonstantin Ananyev            if (n == 0) {
346e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_INFO, c->log, 0,
347e18a033bSKonstantin Ananyev                              "client prematurely closed connection");
348e18a033bSKonstantin Ananyev            }
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev            if (n == 0 || n == NGX_ERROR) {
351e18a033bSKonstantin Ananyev                c->error = 1;
352e18a033bSKonstantin Ananyev                return NGX_HTTP_BAD_REQUEST;
353e18a033bSKonstantin Ananyev            }
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyev            rb->buf->last += n;
356e18a033bSKonstantin Ananyev            r->request_length += n;
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev            if (n == rest) {
359e18a033bSKonstantin Ananyev                /* pass buffer to request body filter chain */
360e18a033bSKonstantin Ananyev
361e18a033bSKonstantin Ananyev                out.buf = rb->buf;
362e18a033bSKonstantin Ananyev                out.next = NULL;
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev                rc = ngx_http_request_body_filter(r, &out);
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev                if (rc != NGX_OK) {
367e18a033bSKonstantin Ananyev                    return rc;
368e18a033bSKonstantin Ananyev                }
369e18a033bSKonstantin Ananyev            }
370e18a033bSKonstantin Ananyev
371e18a033bSKonstantin Ananyev            if (rb->rest == 0) {
372e18a033bSKonstantin Ananyev                break;
373e18a033bSKonstantin Ananyev            }
374e18a033bSKonstantin Ananyev
375e18a033bSKonstantin Ananyev            if (rb->buf->last < rb->buf->end) {
376e18a033bSKonstantin Ananyev                break;
377e18a033bSKonstantin Ananyev            }
378e18a033bSKonstantin Ananyev        }
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
381e18a033bSKonstantin Ananyev                       "http client request body rest %O", rb->rest);
382e18a033bSKonstantin Ananyev
383e18a033bSKonstantin Ananyev        if (rb->rest == 0) {
384e18a033bSKonstantin Ananyev            break;
385e18a033bSKonstantin Ananyev        }
386e18a033bSKonstantin Ananyev
387e18a033bSKonstantin Ananyev        if (!c->read->ready) {
388e18a033bSKonstantin Ananyev
389e18a033bSKonstantin Ananyev            if (r->request_body_no_buffering
390e18a033bSKonstantin Ananyev                && rb->buf->pos != rb->buf->last)
391e18a033bSKonstantin Ananyev            {
392e18a033bSKonstantin Ananyev                /* pass buffer to request body filter chain */
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev                out.buf = rb->buf;
395e18a033bSKonstantin Ananyev                out.next = NULL;
396e18a033bSKonstantin Ananyev
397e18a033bSKonstantin Ananyev                rc = ngx_http_request_body_filter(r, &out);
398e18a033bSKonstantin Ananyev
399e18a033bSKonstantin Ananyev                if (rc != NGX_OK) {
400e18a033bSKonstantin Ananyev                    return rc;
401e18a033bSKonstantin Ananyev                }
402e18a033bSKonstantin Ananyev            }
403e18a033bSKonstantin Ananyev
404e18a033bSKonstantin Ananyev            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
405e18a033bSKonstantin Ananyev            ngx_add_timer(c->read, clcf->client_body_timeout);
406e18a033bSKonstantin Ananyev
407e18a033bSKonstantin Ananyev            if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
408e18a033bSKonstantin Ananyev                return NGX_HTTP_INTERNAL_SERVER_ERROR;
409e18a033bSKonstantin Ananyev            }
410e18a033bSKonstantin Ananyev
411e18a033bSKonstantin Ananyev            return NGX_AGAIN;
412e18a033bSKonstantin Ananyev        }
413e18a033bSKonstantin Ananyev    }
414e18a033bSKonstantin Ananyev
415e18a033bSKonstantin Ananyev    if (c->read->timer_set) {
416e18a033bSKonstantin Ananyev        ngx_del_timer(c->read);
417e18a033bSKonstantin Ananyev    }
418e18a033bSKonstantin Ananyev
419e18a033bSKonstantin Ananyev    if (!r->request_body_no_buffering) {
420