1
/* Copyright (C) agentzh */
7
#include "ngx_http_chunkin_util.h"
9
static ngx_str_t ngx_http_chunkin_content_length_header_key =
10
ngx_string("Content-Length");
14
ngx_http_chunkin_clear_transfer_encoding(ngx_http_request_t *r)
16
if (r->headers_in.transfer_encoding) {
17
r->headers_in.transfer_encoding->value.len = 0;
18
r->headers_in.transfer_encoding->value.data = (u_char *) "";
19
r->headers_in.transfer_encoding->hash = 0;
20
r->headers_in.transfer_encoding = NULL;
26
ngx_http_chunkin_set_content_length_header(ngx_http_request_t *r, size_t len) {
28
ngx_list_part_t *part;
31
r->headers_in.content_length_n = len;
33
part = &r->headers_in.headers.part;
36
for (i = 0; /* void */; i++) {
38
if (i >= part->nelts) {
39
if (part->next == NULL) {
49
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
50
"header value [%V]", &h[i].value);
51
dd("header value (raw): [%s]", h[i].value.data);
54
if (h[i].key.len == ngx_http_chunkin_content_length_header_key.len
55
&& ngx_strncasecmp(h[i].key.data,
56
ngx_http_chunkin_content_length_header_key.data,
59
dd("Found existing content-length header.");
61
h[i].value.data = ngx_palloc(r->pool, NGX_OFF_T_LEN);
63
if (h[i].value.data == NULL) {
64
return NGX_HTTP_INTERNAL_SERVER_ERROR;
67
h[i].value.len = ngx_sprintf(h[i].value.data, "%O",
68
r->headers_in.content_length_n) - h[i].value.data;
74
h = ngx_list_push(&r->headers_in.headers);
77
return NGX_HTTP_INTERNAL_SERVER_ERROR;
80
h->hash = r->header_hash;
82
h->key = ngx_http_chunkin_content_length_header_key;
84
h->value.data = ngx_palloc(r->pool, NGX_OFF_T_LEN);
86
if (h->value.data == NULL) {
87
return NGX_HTTP_INTERNAL_SERVER_ERROR;
90
h->value.len = ngx_sprintf(h->value.data, "%O",
91
r->headers_in.content_length_n) - h->value.data;
93
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
94
if (h->lowcase_key == NULL) {
95
return NGX_HTTP_INTERNAL_SERVER_ERROR;
98
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
100
r->headers_in.content_length = h;
107
ngx_http_chunkin_get_buf(ngx_pool_t *pool, ngx_http_chunkin_ctx_t *ctx)
116
ll = &ctx->free_bufs;
117
for (i = 0; i < 4; i++) {
118
cl = ngx_alloc_chain_link(pool);
123
cl->buf = ngx_calloc_buf(pool);
124
if (cl->buf == NULL) {
136
ctx->free_bufs = cl->next;
138
cl->buf->shadow = NULL;
141
dd("returned free buf");
145
dd("allocate new buf");
147
cl = ngx_alloc_chain_link(pool);
152
cl->buf = ngx_calloc_buf(pool);
153
if (cl->buf == NULL) {
159
/* cl->buf->tag = (ngx_buf_tag_t) &ngx_http_chunkin_filter_module; */
165
/* modified from the ngx_http_internal_redirect function
166
* in ngx_http_core_module.c of nginx 0.8.29.
167
* copyrighted by Igor Sysoev. */
169
ngx_http_chunkin_restart_request(ngx_http_request_t *r,
170
ngx_http_chunkin_ctx_t *ctx)
172
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
173
"chunkin: restart request: \"%V?%V\"",
176
ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
178
ngx_http_set_ctx(r, ctx, ngx_http_chunkin_filter_module);
181
/* r->phase_handler = 0; */
185
#if defined(nginx_version) && nginx_version >= 8011
187
dd("DISCARD BODY: %d", (int)r->discard_body);
189
if ( ! ctx->r_discard_body ) {
199
/* mostly a clone of the ngx_http_process_request_header function
200
* in ngx_http_request.c of nginx 0.8.29.
201
* copyrighted by Igor Sysoev. */
203
ngx_http_chunkin_process_request_header(ngx_http_request_t *r)
205
dd("entered process_request_header");
207
if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
208
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
209
"client sent HTTP/1.1 request without \"Host\" header");
210
return NGX_HTTP_BAD_REQUEST;
213
if (r->headers_in.content_length) {
214
r->headers_in.content_length_n =
215
ngx_atoof(r->headers_in.content_length->value.data,
216
r->headers_in.content_length->value.len);
218
if (r->headers_in.content_length_n == NGX_ERROR) {
219
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
220
"client sent invalid \"Content-Length\" header");
221
return NGX_HTTP_LENGTH_REQUIRED;
225
dd("method: %d (%d)", (int)r->method, (int)NGX_HTTP_PUT);
226
dd("content_length_n: %d (%d)", (int)r->headers_in.content_length_n, -1);
228
if (r->method & NGX_HTTP_PUT && r->headers_in.content_length_n == -1) {
229
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
230
"client sent %V method without \"Content-Length\" header",
232
return NGX_HTTP_LENGTH_REQUIRED;
235
if (r->method & NGX_HTTP_TRACE) {
236
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
237
"client sent TRACE method");
238
return NGX_HTTP_NOT_ALLOWED;
241
if (r->headers_in.transfer_encoding
242
&& ngx_strcasestrn(r->headers_in.transfer_encoding->value.data,
245
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
246
"client sent \"Transfer-Encoding: chunked\" header");
247
return NGX_HTTP_LENGTH_REQUIRED;
250
if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
251
if (r->headers_in.keep_alive) {
252
r->headers_in.keep_alive_n =
253
ngx_atotm(r->headers_in.keep_alive->value.data,
254
r->headers_in.keep_alive->value.len);
262
/* mostly a clone of the ngx_http_process_request function
263
* in ngx_http_request.c of nginx 0.8.29.
264
* copyrighted by Igor Sysoev. */
266
ngx_http_chunkin_process_request(ngx_http_request_t *r)
273
ngx_log_error(NGX_LOG_INFO, c->log, 0,
274
"client sent plain HTTP request to HTTPS port");
275
/* ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS); */
276
return NGX_HTTP_TO_HTTPS;
284
ngx_http_ssl_srv_conf_t *sscf;
286
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
289
rc = SSL_get_verify_result(c->ssl->connection);
291
if (rc != X509_V_OK) {
292
ngx_log_error(NGX_LOG_INFO, c->log, 0,
293
"client SSL certificate verify error: (%l:%s)",
294
rc, X509_verify_cert_error_string(rc));
296
ngx_ssl_remove_cached_session(sscf->ssl.ctx,
297
(SSL_get0_session(c->ssl->connection)));
299
/* ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR); */
300
return NGX_HTTPS_CERT_ERROR;
303
if (sscf->verify == 1) {
304
cert = SSL_get_peer_certificate(c->ssl->connection);
307
ngx_log_error(NGX_LOG_INFO, c->log, 0,
308
"client sent no required SSL certificate");
310
ngx_ssl_remove_cached_session(sscf->ssl.ctx,
311
(SSL_get0_session(c->ssl->connection)));
313
/* ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT); */
314
return NGX_HTTPS_NO_CERT;
324
if (c->read->timer_set) {
325
ngx_del_timer(c->read);
329
(void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
331
(void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
340
ngx_http_chunkin_internal_redirect(ngx_http_request_t *r,
341
ngx_str_t *uri, ngx_str_t *args, ngx_http_chunkin_ctx_t *ctx)
343
ngx_http_core_srv_conf_t *cscf;
347
if (r->uri_changes == 0) {
348
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
349
"rewrite or internal redirection cycle "
350
"while internal redirect to \"%V\"", uri);
352
#if defined(nginx_version) && nginx_version >= 8011
358
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
372
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
373
"internal redirect: \"%V?%V\"", uri, &r->args);
375
ngx_http_set_exten(r);
377
/* clear the modules contexts */
378
ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
380
ngx_http_set_ctx(r, ctx, ngx_http_chunkin_filter_module);
382
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
383
r->loc_conf = cscf->ctx->loc_conf;
385
ngx_http_update_location_config(r);
393
#if defined(nginx_version) && nginx_version >= 8011
395
dd("DISCARD BODY: %d", (int)r->discard_body);
397
if ( ! ctx->r_discard_body ) {