# HG changeset patch # User Igor Sysoev # Date 1112904000 -14400 # Node ID 3050baa54a263a3260cd94348c5d6c13b4b695d2 # Parent 729de7d75018953ed1ffea0702c2b287f96ca5dc nginx 0.1.28 *) Bugfix: nginx hogs CPU while proxying the huge files. *) Bugfix: nginx could not be built by gcc 4.0 on Linux. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,14 @@ + +Changes with nginx 0.1.28 08 Apr 2005 + + *) Bugfix: nginx hogs CPU while proxing the huge files. + + *) Bugfix: nginx could not be built by gcc 4.0 on Linux. + Changes with nginx 0.1.27 28 Mar 2005 - *) Feature: the "blocked" parameter of the "invalid_referers" directive. + *) Feature: the "blocked" parameter of the "valid_referers" directive. *) Change: the errors while handling the request header now logged at "info" level. The server name and the "Host" and "Referer" header diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,7 +1,15 @@ + +Изменения в nginx 0.1.28 08.04.2005 + + *) Исправление: при проксировании больших файлов nginx сильно нагружал + процессор. + + *) Исправление: nginx не собирался gcc 4.0 на Linux. + Изменения в nginx 0.1.27 28.03.2005 - *) Добавление: параметр blocked в директиве invalid_referers. + *) Добавление: параметр blocked в директиве valid_referers. *) Изменение: ошибки обработки заголовка запроса теперь записываются на уровне info, в лог также записывается имя сервера и строки заголовка diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -13,7 +13,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_palloc.h \ src/core/ngx_array.h \ src/core/ngx_list.h \ - src/core/ngx_table.h \ + src/core/ngx_hash.h \ src/core/ngx_buf.h \ src/core/ngx_string.h \ src/core/ngx_parse.h \ @@ -34,6 +34,7 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_palloc.c \ src/core/ngx_array.c \ src/core/ngx_list.c \ + src/core/ngx_hash.c \ src/core/ngx_buf.c \ src/core/ngx_output_chain.c \ src/core/ngx_string.c \ @@ -243,6 +244,7 @@ HTTP_DEPS="src/http/ngx_http.h \ src/http/ngx_http_core_module.h \ src/http/ngx_http_cache.h \ src/http/ngx_http_variables.h \ + src/http/ngx_http_script.h \ src/http/ngx_http_upstream.h \ src/http/ngx_http_busy_lock.h \ src/http/ngx_http_log_module.h" @@ -258,6 +260,7 @@ HTTP_SRCS="src/http/ngx_http.c \ src/http/ngx_http_log_module.c \ src/http/ngx_http_request_body.c \ src/http/ngx_http_variables.c \ + src/http/ngx_http_script.c \ src/http/ngx_http_upstream.c \ src/http/ngx_http_parse_time.c \ src/http/modules/ngx_http_static_module.c \ @@ -320,6 +323,8 @@ HTTP_SSL_SRCS=src/http/modules/ngx_http_ HTTP_PROXY_MODULE=ngx_http_proxy_module +#HTTP_PROXY_SRCS=src/http/modules/ngx_http_proxy_module.c + HTTP_PROXY_INCS="src/http/modules/proxy" HTTP_PROXY_DEPS=src/http/modules/proxy/ngx_http_proxy_handler.h HTTP_PROXY_SRCS="src/http/modules/proxy/ngx_http_proxy_handler.c \ diff --git a/conf/mime.types b/conf/mime.types --- a/conf/mime.types +++ b/conf/mime.types @@ -4,21 +4,27 @@ types { text/xml xml rss; text/css css; text/plain txt; + text/x-component htc; image/gif gif; image/png png; image/jpeg jpeg jpg; image/x-icon ico; + image/x-jng jng; application/pdf pdf; application/x-shockwave-flash swf; application/x-javascript js; + application/x-rar-compressed rar; + application/x-xpinstall xpi; audio/mpeg mp3; audio/x-realaudio ra; video/mpeg mpeg mpg; video/quicktime mov; + video/x-flv flv; video/x-msvideo avi; video/x-ms-wmv wmv; + video/x-mng mng; } diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.1.27" +#define NGINX_VER "nginx/0.1.28" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c --- a/src/core/ngx_buf.c +++ b/src/core/ngx_buf.c @@ -44,6 +44,27 @@ ngx_create_temp_buf(ngx_pool_t *pool, si ngx_chain_t * +ngx_alloc_chain_link(ngx_pool_t *pool) +{ + ngx_chain_t *cl; + + cl = pool->chain; + + if (cl) { + pool->chain = cl->next; + return cl; + } + + cl = ngx_palloc(pool, sizeof(ngx_chain_t)); + if (cl == NULL) { + return NULL; + } + + return cl; +} + + +ngx_chain_t * ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs) { u_char *p; diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h --- a/src/core/ngx_buf.h +++ b/src/core/ngx_buf.h @@ -55,8 +55,6 @@ struct ngx_buf_s { }; -typedef struct ngx_chain_s ngx_chain_t; - struct ngx_chain_s { ngx_buf_t *buf; ngx_chain_t *next; @@ -119,7 +117,11 @@ ngx_chain_t *ngx_create_chain_of_bufs(ng #define ngx_alloc_buf(pool) ngx_palloc(pool, sizeof(ngx_buf_t)) #define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t)) -#define ngx_alloc_chain_link(pool) ngx_palloc(pool, sizeof(ngx_chain_t)) +ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool); +#define ngx_free_chain(pool, cl) \ + cl->next = pool->chain; \ + pool->chain = cl + ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in); diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -137,7 +137,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t } ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "%s in %s:%d", + "%s in %s:%ui", rv, cf->conf_file->file.name.data, cf->conf_file->line); rc = NGX_ERROR; @@ -207,7 +207,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int if (!(cmd->type & cf->cmd_type)) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "directive \"%s\" in %s:%d " + "directive \"%s\" in %s:%ui " "is not allowed here", name->data, cf->conf_file->file.name.data, cf->conf_file->line); @@ -216,7 +216,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "directive \"%s\" in %s:%d " + "directive \"%s\" in %s:%ui " "is not terminated by \";\"", name->data, cf->conf_file->file.name.data, cf->conf_file->line); @@ -227,7 +227,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int && last != NGX_CONF_BLOCK_START) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "directive \"%s\" in %s:%d " + "directive \"%s\" in %s:%ui " "has not the opening \"{\"", name->data, cf->conf_file->file.name.data, cf->conf_file->line); @@ -276,7 +276,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int if (!valid) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "invalid number arguments in " - "directive \"%s\" in %s:%d", + "directive \"%s\" in %s:%ui", name->data, cf->conf_file->file.name.data, cf->conf_file->line); return NGX_ERROR; @@ -311,7 +311,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int } ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "the \"%s\" directive %s in %s:%d", + "the \"%s\" directive %s in %s:%ui", name->data, rv, cf->conf_file->file.name.data, cf->conf_file->line); @@ -323,7 +323,7 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int } ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown directive \"%s\" in %s:%d", + "unknown directive \"%s\" in %s:%ui", name->data, cf->conf_file->file.name.data, cf->conf_file->line); @@ -360,7 +360,7 @@ ngx_conf_read_token(ngx_conf_t *cf) { if (cf->args->nelts > 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unexpected end of file in %s:%d, " + "unexpected end of file in %s:%ui, " "expecting \";\" or \"}\"", cf->conf_file->file.name.data, cf->conf_file->line); @@ -423,7 +423,7 @@ ngx_conf_read_token(ngx_conf_t *cf) } ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unexpected \"%c\" in %s:%d", + "unexpected \"%c\" in %s:%ui", ch, cf->conf_file->file.name.data, cf->conf_file->line); @@ -443,7 +443,7 @@ ngx_conf_read_token(ngx_conf_t *cf) case '{': if (cf->args->nelts == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unexpected \"%c\" in %s:%d", + "unexpected \"%c\" in %s:%ui", ch, cf->conf_file->file.name.data, cf->conf_file->line); return NGX_ERROR; @@ -458,7 +458,7 @@ ngx_conf_read_token(ngx_conf_t *cf) case '}': if (cf->args->nelts > 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unexpected \"}\" in %s:%d", + "unexpected \"}\" in %s:%ui", cf->conf_file->file.name.data, cf->conf_file->line); return NGX_ERROR; @@ -729,7 +729,7 @@ ngx_conf_log_error(ngx_uint_t level, ngx *buf = '\0'; } - ngx_log_error(level, cf->log, 0, "%s in %s:%d", + ngx_log_error(level, cf->log, 0, "%s in %s:%ui", errstr, cf->conf_file->file.name.data, cf->conf_file->line); } @@ -1065,7 +1065,7 @@ ngx_conf_check_num_bounds(ngx_conf_t *cf } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "value must be equal or more than %d", bounds->low); + "value must be equal or more than %i", bounds->low); return NGX_CONF_ERROR; } @@ -1075,7 +1075,7 @@ ngx_conf_check_num_bounds(ngx_conf_t *cf } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "value must be between %d and %d", + "value must be between %i and %i", bounds->low, bounds->high); return NGX_CONF_ERROR; diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -73,60 +73,60 @@ struct ngx_command_s { - ngx_str_t name; - int type; - char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - int conf; - int offset; - void *post; + ngx_str_t name; + ngx_uint_t type; + char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + ngx_uint_t conf; + ngx_uint_t offset; + void *post; }; #define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL } struct ngx_open_file_s { - ngx_fd_t fd; - ngx_str_t name; + ngx_fd_t fd; + ngx_str_t name; #if 0 /* e.g. append mode, error_log */ - int flags; + ngx_uint_t flags; /* e.g. reopen db file */ - int (*handler)(void *data, ngx_open_file_t *file); - void *data; + ngx_uint_t (*handler)(void *data, ngx_open_file_t *file); + void *data; #endif }; struct ngx_module_s { - ngx_uint_t ctx_index; - ngx_uint_t index; - void *ctx; - ngx_command_t *commands; - ngx_uint_t type; - ngx_int_t (*init_module)(ngx_cycle_t *cycle); - ngx_int_t (*init_process)(ngx_cycle_t *cycle); + ngx_uint_t ctx_index; + ngx_uint_t index; + void *ctx; + ngx_command_t *commands; + ngx_uint_t type; + ngx_int_t (*init_module)(ngx_cycle_t *cycle); + ngx_int_t (*init_process)(ngx_cycle_t *cycle); #if 0 - ngx_int_t (*init_thread)(ngx_cycle_t *cycle); + ngx_int_t (*init_thread)(ngx_cycle_t *cycle); #endif }; typedef struct { - ngx_str_t name; - void *(*create_conf)(ngx_cycle_t *cycle); - char *(*init_conf)(ngx_cycle_t *cycle, void *conf); + ngx_str_t name; + void *(*create_conf)(ngx_cycle_t *cycle); + char *(*init_conf)(ngx_cycle_t *cycle, void *conf); } ngx_core_module_t; typedef struct { - ngx_file_t file; - ngx_buf_t *buffer; - ngx_uint_t line; + ngx_file_t file; + ngx_buf_t *buffer; + ngx_uint_t line; } ngx_conf_file_t; typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf, - ngx_command_t *dummy, void *conf); + ngx_command_t *dummy, void *conf); struct ngx_conf_s { @@ -157,22 +157,22 @@ typedef struct { typedef struct { ngx_conf_post_handler_pt post_handler; - int low; - int high; + ngx_int_t low; + ngx_int_t high; } ngx_conf_num_bounds_t; typedef struct { - ngx_str_t name; - ngx_uint_t value; + ngx_str_t name; + ngx_uint_t value; } ngx_conf_enum_t; #define NGX_CONF_BITMASK_SET 1 typedef struct { - ngx_str_t name; - ngx_uint_t mask; + ngx_str_t name; + ngx_uint_t mask; } ngx_conf_bitmask_t; diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -12,6 +12,7 @@ typedef struct ngx_module_s ngx_mod typedef struct ngx_conf_s ngx_conf_t; typedef struct ngx_cycle_s ngx_cycle_t; typedef struct ngx_pool_s ngx_pool_t; +typedef struct ngx_chain_s ngx_chain_t; typedef struct ngx_log_s ngx_log_t; typedef struct ngx_array_s ngx_array_t; typedef struct ngx_open_file_s ngx_open_file_t; @@ -51,7 +52,7 @@ typedef void (*ngx_event_handler_pt)(ngx #include #include #include -#include +#include #include #include #include diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -54,7 +54,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t log = old_cycle->log; - pool = ngx_create_pool(16 * 1024, log); + pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -12,6 +12,11 @@ #include +#ifndef NGX_CYCLE_POOL_SIZE +#define NGX_CYCLE_POOL_SIZE 16384 +#endif + + #define NGX_DEBUG_POINTS_STOP 1 #define NGX_DEBUG_POINTS_ABORT 2 diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c new file mode 100644 --- /dev/null +++ b/src/core/ngx_hash.c @@ -0,0 +1,160 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include + + +ngx_int_t +ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names) +{ + u_char *p; + ngx_str_t *n, *bucket; + ngx_uint_t i, key, size, best, *test, buckets, min_buckets; + + test = ngx_alloc(hash->max_size * sizeof(ngx_uint_t), pool->log); + if (test == NULL) { + return NGX_ERROR; + } + + min_buckets = hash->bucket_limit + 1; + +#if (NGX_SUPPRESS_WARN) + best = 0; +#endif + + for (size = 1; size < hash->max_size; size++) { + + buckets = 0; + + for (i = 0; i < size; i++) { + test[i] = 0; + } + + for (n = (ngx_str_t *) names; + n->len; + n = (ngx_str_t *) ((char *) n + hash->bucket_size)) + { + key = 0; + + for (i = 0; i < n->len; i++) { + key += ngx_tolower(n->data[i]); + } + + key %= size; + + if (test[key] == hash->bucket_limit) { + break; + } + + test[key]++; + + if (buckets < test[key]) { + buckets = test[key]; + } + } + + if (n->len == 0) { + if (min_buckets > buckets) { + min_buckets = buckets; + best = size; + } + + if (hash->bucket_limit == 1) { + break; + } + } + } + + if (min_buckets == hash->bucket_limit + 1) { + ngx_log_error(NGX_LOG_EMERG, pool->log, 0, + "could not build the %s hash, you should increase " + "either %s_size: %i or %s_bucket_limit: %i", + hash->name, hash->name, hash->max_size, + hash->name, hash->bucket_limit); + ngx_free(test); + return NGX_ERROR; + } + + hash->buckets = ngx_pcalloc(pool, best * hash->bucket_size); + if (hash->buckets == NULL) { + ngx_free(test); + return NGX_ERROR; + } + + if (hash->bucket_limit != 1) { + + for (i = 0; i < best; i++) { + test[i] = 0; + } + + for (n = (ngx_str_t *) names; + n->len; + n = (ngx_str_t *) ((char *) n + hash->bucket_size)) + { + key = 0; + + for (i = 0; i < n->len; i++) { + key += ngx_tolower(n->data[i]); + } + + key %= best; + + test[key]++; + } + + for (i = 0; i < best; i++) { + if (test[i] == 0) { + continue; + } + + bucket = ngx_palloc(pool, test[i] * hash->bucket_size); + if (bucket == NULL) { + ngx_free(test); + return NGX_ERROR; + } + + hash->buckets[i] = bucket; + bucket->len = 0; + } + } + + for (n = (ngx_str_t *) names; + n->len; + n = (ngx_str_t *) ((char *) n + hash->bucket_size)) + { + key = 0; + + for (i = 0; i < n->len; i++) { + key += ngx_tolower(n->data[i]); + } + + key %= best; + + if (hash->bucket_limit == 1) { + p = (u_char *) hash->buckets + key * hash->bucket_size; + ngx_memcpy(p, n, hash->bucket_size); + continue; + } + + for (bucket = hash->buckets[key]; + bucket->len; + bucket = (ngx_str_t *) ((char *) bucket + hash->bucket_size)) + { + bucket->len &= 0x7fffffff; + } + + ngx_memcpy(bucket, n, hash->bucket_size); + bucket->len |= 0x80000000; + } + + ngx_free(test); + + hash->hash_size = best; + hash->min_buckets = min_buckets; + + return NGX_OK; +} diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_hash.h @@ -0,0 +1,37 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_HASH_H_INCLUDED_ +#define _NGX_HASH_H_INCLUDED_ + + +#include +#include + + +typedef struct { + void **buckets; + ngx_uint_t hash_size; + + ngx_uint_t max_size; + ngx_uint_t bucket_limit; + size_t bucket_size; + char *name; + ngx_uint_t min_buckets; +} ngx_hash_t; + + +typedef struct { + ngx_uint_t hash; + ngx_str_t key; + ngx_str_t value; +} ngx_table_elt_t; + + +ngx_int_t ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names); + + +#endif /* _NGX_HASH_H_INCLUDED_ */ diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -119,8 +119,10 @@ ngx_output_chain(ngx_output_chain_ctx_t /* get the free buf */ if (ctx->free) { - ctx->buf = ctx->free->buf; - ctx->free = ctx->free->next; + cl = ctx->free; + ctx->buf = cl->buf; + ctx->free = cl->next; + ngx_free_chain(ctx->pool, cl); } else if (out || ctx->allocated == ctx->bufs.num) { diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -22,6 +22,7 @@ ngx_create_pool(size_t size, ngx_log_t * p->end = (u_char *) p + size; p->next = NULL; p->large = NULL; + p->chain = NULL; p->log = log; return p; diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -33,6 +33,7 @@ struct ngx_pool_large_s { struct ngx_pool_s { u_char *last; u_char *end; + ngx_chain_t *chain; ngx_pool_t *next; ngx_pool_large_t *large; ngx_log_t *log; diff --git a/src/core/ngx_table.h b/src/core/ngx_table.h deleted file mode 100644 --- a/src/core/ngx_table.h +++ /dev/null @@ -1,27 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - */ - - -#ifndef _NGX_TABLE_H_INCLUDED_ -#define _NGX_TABLE_H_INCLUDED_ - - -#include -#include - - -typedef ngx_array_t ngx_table_t; - -typedef struct { - ngx_str_t key; - ngx_str_t value; -} ngx_table_elt_t; - - -#define ngx_create_table(p, n) ngx_create_array(p, n, 2 * sizeof(ngx_str_t)) -#define ngx_push_table(t) ngx_push_array(t) - - -#endif /* _NGX_TABLE_H_INCLUDED_ */ diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -84,7 +84,7 @@ static ngx_int_t ngx_event_pipe_read_ups ssize_t n, size; ngx_int_t rc; ngx_buf_t *b; - ngx_chain_t *chain, *cl; + ngx_chain_t *chain, *cl, *ln; if (p->upstream_eof || p->upstream_error || p->upstream_done) { return NGX_OK; @@ -293,7 +293,9 @@ static ngx_int_t ngx_event_pipe_read_ups } n -= size; + ln = cl; cl = cl->next; + ngx_free_chain(p->pool, ln); } else { cl->buf->last += n; @@ -686,8 +688,10 @@ ngx_int_t ngx_event_pipe_copy_input_filt } if (p->free) { - b = p->free->buf; - p->free = p->free->next; + cl = p->free; + b = cl->buf; + p->free = cl->next; + ngx_free_chain(p->pool, cl); } else { b = ngx_alloc_buf(p->pool); diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -396,7 +396,7 @@ ngx_http_fastcgi_handler(ngx_http_reques u->conf = &flcf->upstream; - u->location = flcf->location; + u->location0 = flcf->location; u->create_request = ngx_http_fastcgi_create_request; u->reinit_request = ngx_http_fastcgi_reinit_request; @@ -411,10 +411,10 @@ ngx_http_fastcgi_handler(ngx_http_reques u->log_ctx = r->connection->log->data; u->log_handler = ngx_http_upstream_log_error; - u->schema.len = sizeof("fastcgi://") - 1; - u->schema.data = (u_char *) "fastcgi://"; - u->uri.len = sizeof("/") - 1; - u->uri.data = (u_char *) "/"; + u->schema0.len = sizeof("fastcgi://") - 1; + u->schema0.data = (u_char *) "fastcgi://"; + u->uri0.len = sizeof("/") - 1; + u->uri0.data = (u_char *) "/"; r->upstream = u; @@ -1244,7 +1244,8 @@ ngx_http_fastcgi_reinit_request(ngx_http } -static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r) +static ngx_int_t +ngx_http_fastcgi_process_header(ngx_http_request_t *r) { u_char *start, *last; ngx_str_t *status_line, line; @@ -2127,16 +2128,16 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE; - conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE; - conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE; - conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE; conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE; conf->upstream.redirect_errors = NGX_CONF_UNSET; + conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET; conf->upstream.x_powered_by = NGX_CONF_UNSET; /* "fastcgi_cyclic_temp_file" is disabled */ @@ -2156,25 +2157,21 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); + ngx_conf_merge_msec_value(conf->upstream.send_timeout, prev->upstream.send_timeout, 60000); - ngx_conf_merge_size_value(conf->upstream.send_lowat, - prev->upstream.send_lowat, 0); ngx_conf_merge_msec_value(conf->upstream.read_timeout, prev->upstream.read_timeout, 60000); - ngx_conf_merge_msec_value(conf->upstream.redirect_errors, - prev->upstream.redirect_errors, 0); - - ngx_conf_merge_msec_value(conf->upstream.x_powered_by, - prev->upstream.x_powered_by, 1); - + ngx_conf_merge_size_value(conf->upstream.send_lowat, + prev->upstream.send_lowat, 0); ngx_conf_merge_size_value(conf->upstream.header_buffer_size, prev->upstream.header_buffer_size, (size_t) ngx_pagesize); + ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs, 8, ngx_pagesize); @@ -2267,6 +2264,23 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_garbage_collector_temp_handler, cf); + ngx_conf_merge_msec_value(conf->upstream.redirect_errors, + prev->upstream.redirect_errors, 0); + + ngx_conf_merge_msec_value(conf->upstream.pass_unparsed_uri, + prev->upstream.pass_unparsed_uri, 0); + + if (conf->upstream.pass_unparsed_uri && conf->location->len > 1) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "\"fastcgi_pass_unparsed_uri\" can be set for " + "location \"/\" or given by regular expression."); + return NGX_CONF_ERROR; + } + + ngx_conf_merge_msec_value(conf->upstream.x_powered_by, + prev->upstream.x_powered_by, 1); + + ngx_conf_merge_bitmask_value(conf->params, prev->params, (NGX_CONF_BITMASK_SET |NGX_HTTP_FASTCGI_REMOTE_ADDR @@ -2290,5 +2304,10 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf conf->vars = prev->vars; } + if (conf->peers == NULL) { + conf->peers = prev->peers; + conf->upstream = prev->upstream; + } + return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -1021,6 +1021,7 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com regex->uri = 1; regex->args = 1; regex->redirect = 0; + regex->break_cycle = 0; regex->name = value[1]; last = 0; @@ -1466,6 +1467,7 @@ ngx_http_rewrite_if_condition(ngx_conf_t regex->uri = 0; regex->args = 0; regex->redirect = 0; + regex->break_cycle = 0; regex->name = value[last]; return NGX_CONF_OK; diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -197,6 +197,12 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } +#if 0 + SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL); + SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_SINGLE_DH_USE); +#endif + if (conf->ciphers.len) { if (SSL_CTX_set_cipher_list(conf->ssl_ctx, (const char *) conf->ciphers.data) == 0) diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -1332,6 +1332,11 @@ static char *ngx_http_proxy_merge_loc_co conf->x_vars = prev->x_vars; } + if (conf->peers == NULL) { + conf->peers = prev->peers; + conf->upstream = prev->upstream; + } + return NULL; } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -90,7 +90,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma ngx_memzero(&in_ports, sizeof(ngx_array_t)); #endif - /* the main http context */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); @@ -317,6 +316,22 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma cmcf->phases[NGX_HTTP_CONTENT_PHASE].type = NGX_OK; + cmcf->headers_in_hash.max_size = 100; + cmcf->headers_in_hash.bucket_limit = 1; + cmcf->headers_in_hash.bucket_size = sizeof(ngx_http_header_t); + cmcf->headers_in_hash.name = "http headers_in"; + + if (ngx_hash_init(&cmcf->headers_in_hash, cf->pool, ngx_http_headers_in) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, + "http headers_in hash size: %ui, max buckets per entry: %ui", + cmcf->headers_in_hash.hash_size, + cmcf->headers_in_hash.min_buckets); + /* * create the lists of ports, addresses and server names * to quickly find the server core module configuration at run-time diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -32,6 +32,7 @@ typedef struct ngx_http_variable_value_s #include #include #include +#include #if (NGX_HTTP_SSL) #include diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -48,6 +48,8 @@ typedef struct { ngx_http_phase_t phases[NGX_HTTP_LAST_PHASE]; ngx_array_t index_handlers; + ngx_hash_t headers_in_hash; + ngx_uint_t server_names_hash; ngx_uint_t server_names_hash_threshold; diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -11,7 +11,7 @@ ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) { - u_char ch, *p, *m; + u_char c, ch, *p, *m; enum { sw_start = 0, sw_method, @@ -109,7 +109,9 @@ ngx_int_t ngx_http_parse_request_line(ng /* space* before URI */ case sw_spaces_before_uri: - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { r->schema_start = p; state = sw_schema; break; @@ -128,7 +130,9 @@ ngx_int_t ngx_http_parse_request_line(ng break; case sw_schema: - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { break; } @@ -164,8 +168,13 @@ ngx_int_t ngx_http_parse_request_line(ng break; case sw_host: - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') - || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-') + + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { + break; + } + + if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') { break; } @@ -204,10 +213,13 @@ ngx_int_t ngx_http_parse_request_line(ng /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: - if ((ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (ch >= '0' && ch <= '9')) - { + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { + state = sw_check_uri; + break; + } + + if (ch >= '0' && ch <= '9') { state = sw_check_uri; break; } @@ -263,10 +275,12 @@ ngx_int_t ngx_http_parse_request_line(ng /* check "/", "%" and "\" (Win32) in URI */ case sw_check_uri: - if ((ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (ch >= '0' && ch <= '9')) - { + c = (u_char) (ch | 0x20); + if (c >= 'a' && c <= 'f') { + break; + } + + if (ch >= '0' && ch <= '9') { break; } @@ -490,7 +504,8 @@ done: ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b) { - u_char c, ch, *p; + u_char c, ch, *p; + ngx_uint_t hash; enum { sw_start = 0, sw_name, @@ -504,6 +519,7 @@ ngx_int_t ngx_http_parse_header_line(ngx } state; state = r->state; + hash = r->header_hash; for (p = b->pos; p < b->last; p++) { ch = *p; @@ -528,14 +544,17 @@ ngx_int_t ngx_http_parse_header_line(ngx c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { + hash = c; break; } if (ch == '-') { + hash = ch; break; } if (ch >= '0' && ch <= '9') { + hash = ch; break; } @@ -550,6 +569,7 @@ ngx_int_t ngx_http_parse_header_line(ngx case sw_name: c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { + hash += c; break; } @@ -560,10 +580,12 @@ ngx_int_t ngx_http_parse_header_line(ngx } if (ch == '-') { + hash += ch; break; } if (ch >= '0' && ch <= '9') { + hash += ch; break; } @@ -681,6 +703,7 @@ ngx_int_t ngx_http_parse_header_line(ngx b->pos = p; r->state = state; + r->header_hash = hash; return NGX_AGAIN; @@ -688,6 +711,7 @@ done: b->pos = p + 1; r->state = sw_start; + r->header_hash = hash; return NGX_OK; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -344,7 +344,7 @@ void ngx_http_init_request(ngx_event_t * if (c->ssl == NULL) { if (ngx_ssl_create_session(sscf->ssl_ctx, c, NGX_SSL_BUFFER) - == NGX_ERROR) + == NGX_ERROR) { ngx_http_close_connection(c); return; @@ -707,12 +707,15 @@ ngx_http_process_request_line(ngx_event_ static void ngx_http_process_request_headers(ngx_event_t *rev) { - ssize_t n; - ngx_int_t rc, rv, i; - ngx_str_t header; - ngx_table_elt_t *h, **cookie; - ngx_connection_t *c; - ngx_http_request_t *r; + ssize_t n; + ngx_int_t rc, rv; + ngx_uint_t key; + ngx_str_t header; + ngx_table_elt_t *h, **cookie; + ngx_connection_t *c; + ngx_http_header_t *hh; + ngx_http_request_t *r; + ngx_http_core_main_conf_t *cmcf; c = rev->data; r = c->data; @@ -728,6 +731,9 @@ ngx_http_process_request_headers(ngx_eve return; } + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + hh = (ngx_http_header_t *) cmcf->headers_in_hash.buckets; + rc = NGX_AGAIN; for ( ;; ) { @@ -791,6 +797,8 @@ ngx_http_process_request_headers(ngx_eve return; } + h->hash = r->header_hash; + h->key.len = r->header_name_end - r->header_name_start; h->key.data = r->header_name_start; h->key.data[h->key.len] = '\0'; @@ -812,19 +820,13 @@ ngx_http_process_request_headers(ngx_eve *cookie = h; } else { - - for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) { - if (ngx_http_headers_in[i].name.len != h->key.len) { - continue; - } - - if (ngx_strcasecmp(ngx_http_headers_in[i].name.data, - h->key.data) == 0) - { - *((ngx_table_elt_t **) ((char *) &r->headers_in - + ngx_http_headers_in[i].offset)) = h; - break; - } + key = h->hash % cmcf->headers_in_hash.hash_size; + + if (hh[key].name.len == h->key.len + && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0) + { + *((ngx_table_elt_t **) + ((char *) &r->headers_in + hh[key].offset)) = h; } } @@ -1237,9 +1239,9 @@ ngx_http_find_virtual_server(ngx_http_re ngx_int_t rc; ngx_uint_t i, n, key, found; ngx_http_server_name_t *name; - ngx_http_core_main_conf_t *cmcf; + ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; + ngx_http_core_main_conf_t *cmcf; if (r->virtual_names->hash) { cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -386,11 +386,12 @@ struct ngx_http_request_s { u_char *header_name_end; u_char *header_start; u_char *header_end; + ngx_uint_t header_hash; }; -extern ngx_http_header_t ngx_http_headers_in[]; -extern ngx_http_header_t ngx_http_headers_out[]; +extern ngx_http_header_t ngx_http_headers_in[]; +extern ngx_http_header_t ngx_http_headers_out[]; diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c new file mode 100644 --- /dev/null +++ b/src/http/ngx_http_script.c @@ -0,0 +1,194 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include +#include + + +ngx_int_t +ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources, + ngx_array_t **lengths, ngx_array_t **values, + ngx_http_script_compile_lite_start_pt start, + ngx_http_script_compile_lite_end_pt end) +{ + uintptr_t *code; + ngx_uint_t i; + ngx_table_elt_t *src; + ngx_http_variable_t *var; + ngx_http_script_var_code_t *var_code; + + if (sources->nelts == 0) { + return NGX_OK; + } + + if (*lengths == NULL) { + *lengths = ngx_array_create(cf->pool, 64, 1); + if (*lengths == NULL) { + return NGX_ERROR; + } + } + + if (*values == NULL) { + *values = ngx_array_create(cf->pool, 256, 1); + if (*values == NULL) { + return NGX_ERROR; + } + } + + src = sources->elts; + for (i = 0; i < sources->nelts; i++) { + + if (src[i].value.data[0] == '$') { + if (start(&src[i], *lengths, *values, 0) != NGX_OK) { + return NGX_ERROR; + } + + src[i].value.len--; + src[i].value.data++; + + var = ngx_http_add_variable(cf, &src[i].value, 0); + + if (var == NULL) { + return NGX_ERROR; + } + + var_code = ngx_array_push_n(*lengths, + sizeof(ngx_http_script_var_code_t)); + if (var_code == NULL) { + return NGX_ERROR; + } + + var_code->code = (ngx_http_script_code_pt) + ngx_http_script_copy_var_len; + var_code->index = var->index; + + + var_code = ngx_array_push_n(*values, + sizeof(ngx_http_script_var_code_t)); + if (var_code == NULL) { + return NGX_ERROR; + } + + var_code->code = ngx_http_script_copy_var; + var_code->index = var->index; + + + if (end(*lengths, *values) != NGX_OK) { + return NGX_ERROR; + } + + continue; + } + + if (start(&src[i], *lengths, *values, 1) != NGX_OK) { + return NGX_ERROR; + } + } + + code = ngx_array_push_n(*lengths, sizeof(uintptr_t)); + if (code == NULL) { + return NGX_ERROR; + } + + *code = (uintptr_t) NULL; + + code = ngx_array_push_n(*values, sizeof(uintptr_t)); + if (code == NULL) { + return NGX_ERROR; + } + + *code = (uintptr_t) NULL; + + return NGX_OK; +} + + +#if 0 + +static void * +ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size) +{ + if (*codes == NULL) { + *codes = ngx_array_create(pool, 256, 1); + if (*codes == NULL) { + return NULL; + } + } + + return ngx_array_push_n(*codes, size); +} + +#endif + + +size_t +ngx_http_script_copy_len(ngx_http_script_engine_t *e) +{ + ngx_http_script_copy_code_t *code; + + code = (ngx_http_script_copy_code_t *) e->lite.ip; + + e->lite.ip += sizeof(ngx_http_script_copy_code_t); + + return code->len; +} + + +void +ngx_http_script_copy(ngx_http_script_engine_t *e) +{ + ngx_http_script_copy_code_t *code; + + code = (ngx_http_script_copy_code_t *) e->lite.ip; + + e->lite.pos = ngx_cpymem(e->lite.pos, + e->lite.ip + sizeof(ngx_http_script_copy_code_t), + code->len); + + e->lite.ip += sizeof(ngx_http_script_copy_code_t) + + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1)); +} + + +size_t +ngx_http_script_copy_var_len(ngx_http_script_engine_t *e) +{ + ngx_http_variable_value_t *value; + ngx_http_script_var_code_t *code; + + code = (ngx_http_script_var_code_t *) e->lite.ip; + + e->lite.ip += sizeof(ngx_http_script_var_code_t); + + value = ngx_http_get_indexed_variable(e->lite.request, code->index); + + if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) { + return 0; + } + + return value->text.len; +} + + +void +ngx_http_script_copy_var(ngx_http_script_engine_t *e) +{ + ngx_http_variable_value_t *value; + ngx_http_script_var_code_t *code; + + code = (ngx_http_script_var_code_t *) e->lite.ip; + + e->lite.ip += sizeof(ngx_http_script_var_code_t); + + value = ngx_http_get_indexed_variable(e->lite.request, code->index); + + if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) { + return; + } + + e->lite.pos = ngx_cpymem(e->lite.pos, value->text.data, value->text.len); +} diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h new file mode 100644 --- /dev/null +++ b/src/http/ngx_http_script.h @@ -0,0 +1,66 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_HTTP_SCRIPT_H_INCLUDED_ +#define _NGX_HTTP_SCRIPT_H_INCLUDED_ + + +#include +#include +#include + + +typedef struct { + u_char *ip; + u_char *pos; + ngx_http_request_t *request; +} ngx_http_script_lite_engine_t; + + +typedef struct { + ngx_http_script_lite_engine_t lite; +} ngx_http_script_engine_t; + + +typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e); +typedef size_t (*ngx_http_script_len_code_pt) + (ngx_http_script_lite_engine_t *e); + +typedef ngx_int_t (*ngx_http_script_compile_lite_start_pt) (ngx_table_elt_t *h, + ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value); +typedef ngx_int_t (*ngx_http_script_compile_lite_end_pt) (ngx_array_t *lengths, + ngx_array_t *values); + + +typedef struct { + ngx_http_script_code_pt code; + uintptr_t len; +} ngx_http_script_copy_code_t; + + +typedef struct { + ngx_http_script_code_pt code; + uintptr_t index; +} ngx_http_script_var_code_t; + + +ngx_int_t ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources, + ngx_array_t **lengths, ngx_array_t **values, + ngx_http_script_compile_lite_start_pt start, + ngx_http_script_compile_lite_end_pt end); + + +static void *ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, + size_t size); + +size_t ngx_http_script_copy_len(ngx_http_script_engine_t *e); +void ngx_http_script_copy(ngx_http_script_engine_t *e); +size_t ngx_http_script_copy_var_len(ngx_http_script_engine_t *e); +void ngx_http_script_copy_var(ngx_http_script_engine_t *e); + + + +#endif /* _NGX_HTTP_SCRIPT_H_INCLUDED_ */ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1135,7 +1135,7 @@ u_char * ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len) { u_char *p; - ngx_int_t escape; + uintptr_t escape; ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_upstream_t *u; @@ -1153,29 +1153,29 @@ ngx_http_upstream_log_error(ngx_log_t *l &r->connection->addr_text, &r->server_name, &r->unparsed_uri, - &u->schema, + &u->schema0, &peer->peers->peer[peer->cur_peer].name, peer->peers->peer[peer->cur_peer].uri_separator, - &u->uri); + &u->uri0); len -= p - buf; buf = p; if (r->quoted_uri) { - escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location->len, - r->uri.len - u->location->len, + escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location0->len, + r->uri.len - u->location0->len, NGX_ESCAPE_URI); } else { escape = 0; } if (escape) { - if (len >= r->uri.len - u->location->len + escape) { + if (len >= r->uri.len - u->location0->len + escape) { - ngx_escape_uri(buf, r->uri.data + u->location->len, - r->uri.len - u->location->len, NGX_ESCAPE_URI); + ngx_escape_uri(buf, r->uri.data + u->location0->len, + r->uri.len - u->location0->len, NGX_ESCAPE_URI); - buf += r->uri.len - u->location->len + escape; - len -= r->uri.len - u->location->len + escape; + buf += r->uri.len - u->location0->len + escape; + len -= r->uri.len - u->location0->len + escape; if (r->args.len) { p = ngx_snprintf(buf, len, "?%V", &r->args); @@ -1186,19 +1186,19 @@ ngx_http_upstream_log_error(ngx_log_t *l return ngx_http_log_error_info(r, buf, len); } - p = ngx_palloc(r->pool, r->uri.len - u->location->len + escape); + p = ngx_palloc(r->pool, r->uri.len - u->location0->len + escape); if (p == NULL) { return buf; } - ngx_escape_uri(p, r->uri.data + u->location->len, - r->uri.len - u->location->len, NGX_ESCAPE_URI); + ngx_escape_uri(p, r->uri.data + u->location0->len, + r->uri.len - u->location0->len, NGX_ESCAPE_URI); - p = ngx_cpymem(buf, p, r->uri.len - u->location->len + escape); + p = ngx_cpymem(buf, p, r->uri.len - u->location0->len + escape); } else { - p = ngx_cpymem(buf, r->uri.data + u->location->len, - r->uri.len - u->location->len); + p = ngx_cpymem(buf, r->uri.data + u->location0->len, + r->uri.len - u->location0->len); } len -= p - buf; diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -55,6 +55,7 @@ typedef struct { ngx_bufs_t bufs; ngx_flag_t redirect_errors; + ngx_flag_t pass_unparsed_uri; ngx_flag_t x_powered_by; ngx_flag_t cyclic_temp_file; @@ -87,9 +88,9 @@ struct ngx_http_upstream_s { ngx_int_t rc); ngx_uint_t method; - ngx_str_t schema; - ngx_str_t uri; - ngx_str_t *location; + ngx_str_t schema0; + ngx_str_t uri0; + ngx_str_t *location0; ngx_http_log_ctx_t *log_ctx; ngx_log_handler_pt log_handler; diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c --- a/src/http/ngx_http_write_filter_module.c +++ b/src/http/ngx_http_write_filter_module.c @@ -231,6 +231,12 @@ ngx_http_write_filter(ngx_http_request_t return NGX_ERROR; } + for (cl = ctx->out; cl && cl != chain; /* void */) { + ln = cl; + cl = cl->next; + ngx_free_chain(r->pool, ln); + } + ctx->out = chain; if (chain || (last && c->buffered)) { diff --git a/src/os/unix/ngx_setproctitle.c b/src/os/unix/ngx_setproctitle.c --- a/src/os/unix/ngx_setproctitle.c +++ b/src/os/unix/ngx_setproctitle.c @@ -88,7 +88,7 @@ ngx_setproctitle(char *title) ngx_os_argv[1] = NULL; - p = ngx_cpystrn((u_char *) ngx_os_argv[0], "nginx: ", + p = ngx_cpystrn((u_char *) ngx_os_argv[0], (u_char *) "nginx: ", ngx_os_argv_last - ngx_os_argv[0]); p = ngx_cpystrn(p, (u_char *) title, ngx_os_argv_last - (char *) p);