# HG changeset patch # User Igor Sysoev # Date 1160424000 -14400 # Node ID 500a3242dff6e71eb03c087be430643792d4a0ce # Parent d371c9d337813b57838a8e6973e6af9e9fc49685 nginx 0.4.7 *) Feature: the ngx_http_flv_module. *) Feature: the $request_body_file variable. *) Feature: the "charset" and "source_charset" directives support the variables. *) Bugfix: if an "include" SSI command were before another "include" SSI command with an "wait" parameter, then the "wait" parameter might not work. *) Bugfix: if the "proxy_buffering off" directive was used or while working with memcached the connections might not be closed on timeout. *) Bugfix: nginx did not run on 64-bit platforms except amd64, sparc64, and ppc64. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,25 @@ +Changes with nginx 0.4.7 10 Oct 2006 + + *) Feature: the ngx_http_flv_module. + + *) Feature: the $request_body_file variable. + + *) Feature: the "charset" and "source_charset" directives support the + variables. + + *) Bugfix: if before an "include" SSI command with an "wait" parameter + were yet another "include" SSI command, then the "wait" parameter + might not work. + + *) Bugfix: if the "proxy_buffering off" directive was used or while + working with memcached the connections might not be closed on + timeout. + + *) Bugfix: nginx did not run on 64-bit platforms except amd64, sparc64, + and ppc64. + + Changes with nginx 0.4.6 06 Oct 2006 *) Bugfix: nginx did not run on 64-bit platforms except amd64, sparc64, diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,7 +1,27 @@ +Изменения в nginx 0.4.7 10.10.2006 + + *) Добавление: модуль ngx_http_flv_module. + + *) Добавление: переменная $request_body_file. + + *) Добавление: директивы charset и source_charset поддерживают + переменные. + + *) Исправление: если до команды SSI include с параметром wait + выполнялась ещё одна команда SSI include, то параметр wait мог не + работать. + + *) Исправление: при использовании директивы "proxy_buffering off" или + при работе с memcached соединения могли не закрываться по таймауту. + + *) Исправление: nginx не запускался на 64-битных платформах, отличных + от amd64, sparc64 и ppc64. + + Изменения в nginx 0.4.6 06.10.2006 - *) Исправление: nginx не запускался на 64-битных платформах, отличной + *) Исправление: nginx не запускался на 64-битных платформах, отличных от amd64, sparc64 и ppc64. *) Исправление: при запросе версии HTTP/1.1 nginx передавал ответ diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -250,6 +250,11 @@ if [ $HTTP_BROWSER = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_BROWSER_SRCS" fi +if [ $HTTP_FLV = YES ]; then + HTTP_MODULES="$HTTP_MODULES $HTTP_FLV_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_FLV_SRCS" +fi + # STUB #USE_MD5=YES #HTTP_SRCS="$HTTP_SRCS $HTPP_CACHE_SRCS" diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -70,6 +70,7 @@ HTTP_PERL=NO HTTP_MEMCACHED=YES HTTP_EMPTY_GIF=YES HTTP_BROWSER=YES +HTTP_FLV=NO # STUB HTTP_STUB_STATUS=NO @@ -150,6 +151,7 @@ do --with-http_realip_module) HTTP_REALIP=YES ;; --with-http_addition_module) HTTP_ADDITION=YES ;; --with-http_dav_module) HTTP_DAV=YES ;; + --with-http_flv_module) HTTP_FLV=YES ;; --without-http_charset_module) HTTP_CHARSET=NO ;; --without-http_gzip_module) HTTP_GZIP=NO ;; @@ -251,6 +253,7 @@ cat << END --with-http_realip_module enable ngx_http_realip_module --with-http_addition_module enable ngx_http_addition_module --with-http_dav_module enable ngx_http_dav_module + --with-http_flv_module enable ngx_http_flv_module --without-http_charset_module disable ngx_http_charset_module --without-http_gzip_module disable ngx_http_gzip_module diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -393,6 +393,10 @@ HTTP_BROWSER_MODULE=ngx_http_browser_mod HTTP_BROWSER_SRCS=src/http/modules/ngx_http_browser_module.c +HTTP_FLV_MODULE=ngx_http_flv_module +HTTP_FLV_SRCS=src/http/modules/ngx_http_flv_module.c + + IMAP_INCS="src/imap" IMAP_DEPS="src/imap/ngx_imap.h" 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.4.6" +#define NGINX_VER "nginx/0.4.7" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c @@ -498,7 +498,7 @@ ngx_eventport_process_events(ngx_cycle_t wev->active = 0; if (revents & POLLIN) { - + if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c --- a/src/http/modules/ngx_http_addition_filter_module.c +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -124,6 +124,7 @@ ngx_http_addition_body_filter(ngx_http_r ngx_int_t rc; ngx_uint_t last; ngx_chain_t *cl; + ngx_http_request_t *sr; ngx_http_addition_ctx_t *ctx; ngx_http_addition_conf_t *conf; @@ -143,7 +144,7 @@ ngx_http_addition_body_filter(ngx_http_r ctx->before_body_sent = 1; if (conf->before_body.len) { - if (ngx_http_subrequest(r, &conf->before_body, NULL, NULL, 0) + if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0) == NGX_ERROR) { return NGX_ERROR; @@ -167,7 +168,9 @@ ngx_http_addition_body_filter(ngx_http_r return rc; } - if (ngx_http_subrequest(r, &conf->after_body, NULL, NULL, 0) == NGX_ERROR) { + if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) + == NGX_ERROR) + { return NGX_ERROR; } diff --git a/src/http/modules/ngx_http_browser_module.c b/src/http/modules/ngx_http_browser_module.c --- a/src/http/modules/ngx_http_browser_module.c +++ b/src/http/modules/ngx_http_browser_module.c @@ -61,7 +61,7 @@ static ngx_int_t ngx_http_browser_variab static ngx_uint_t ngx_http_browser(ngx_http_request_t *r, ngx_http_browser_conf_t *cf); - + static ngx_int_t ngx_http_browser_add_variable(ngx_conf_t *cf); static void *ngx_http_browser_create_conf(ngx_conf_t *cf); static char *ngx_http_browser_merge_conf(ngx_conf_t *cf, void *parent, diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c --- a/src/http/modules/ngx_http_charset_filter_module.c +++ b/src/http/modules/ngx_http_charset_filter_module.c @@ -10,6 +10,7 @@ #define NGX_HTTP_NO_CHARSET -2 +#define NGX_HTTP_CHARSET_VAR 0x10000 /* 1 byte length and up to 3 bytes for the UTF-8 encoding of the UCS-2 */ #define NGX_UTF_LEN 4 @@ -79,7 +80,7 @@ typedef struct { static ngx_int_t ngx_http_charset_get_charset(ngx_http_charset_t *charsets, - ngx_uint_t n, u_char *charset); + ngx_uint_t n, ngx_str_t *charset); static ngx_int_t ngx_http_charset_set_charset(ngx_http_request_t *r, ngx_http_charset_t *charsets, ngx_int_t charset, ngx_int_t source_charset); static ngx_uint_t ngx_http_charset_recode(ngx_buf_t *b, u_char *table); @@ -190,6 +191,7 @@ ngx_http_charset_header_filter(ngx_http_ ngx_uint_t n; ngx_http_charset_t *charsets; ngx_http_charset_ctx_t *ctx; + ngx_http_variable_value_t *vv; ngx_http_charset_loc_conf_t *lcf, *mlcf; ngx_http_charset_main_conf_t *mcf; @@ -210,7 +212,7 @@ ngx_http_charset_header_filter(ngx_http_ && r->headers_out.override_charset->len) { charset = ngx_http_charset_get_charset(charsets, n, - r->headers_out.override_charset->data); + r->headers_out.override_charset); if (charset == NGX_HTTP_NO_CHARSET) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -243,6 +245,14 @@ ngx_http_charset_header_filter(ngx_http_ return ngx_http_next_header_filter(r); } } + + if (charset >= NGX_HTTP_CHARSET_VAR) { + vv = ngx_http_get_indexed_variable(r, + charset - NGX_HTTP_CHARSET_VAR); + + charset = ngx_http_charset_get_charset(charsets, n, + (ngx_str_t *) vv); + } } } else { @@ -263,7 +273,7 @@ ngx_http_charset_header_filter(ngx_http_ ngx_http_set_ctx(r->main, ctx, ngx_http_charset_filter_module); - charset = ngx_http_charset_get_charset(charsets, n, mc->data); + charset = ngx_http_charset_get_charset(charsets, n, mc); ctx->charset = charset; @@ -277,23 +287,33 @@ ngx_http_charset_header_filter(ngx_http_ if (r->headers_out.charset.len == 0) { lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module); + source_charset = lcf->source_charset; + + if (source_charset >= NGX_HTTP_CHARSET_VAR) { + vv = ngx_http_get_indexed_variable(r, + source_charset - NGX_HTTP_CHARSET_VAR); + + source_charset = ngx_http_charset_get_charset(charsets, n, + (ngx_str_t *) vv); + } + if (charset != NGX_HTTP_NO_CHARSET) { return ngx_http_charset_set_charset(r, mcf->charsets.elts, charset, - lcf->source_charset); + source_charset); } - if (lcf->source_charset == NGX_CONF_UNSET) { + if (source_charset == NGX_CONF_UNSET) { return ngx_http_next_header_filter(r); } - from = &charsets[lcf->source_charset].name; + from = &charsets[source_charset].name; to = &r->main->headers_out.charset; goto no_charset_map; } source_charset = ngx_http_charset_get_charset(charsets, n, - r->headers_out.charset.data); + &r->headers_out.charset); if (charset == NGX_HTTP_NO_CHARSET || source_charset == NGX_HTTP_NO_CHARSET) @@ -341,12 +361,19 @@ no_charset_map: static ngx_int_t ngx_http_charset_get_charset(ngx_http_charset_t *charsets, ngx_uint_t n, - u_char *charset) + ngx_str_t *charset) { + size_t len; ngx_uint_t i; + len = charset->len & 0xffff; + for (i = 0; i < n; i++) { - if (ngx_strcasecmp(charsets[i].name.data, charset) == 0) { + if (charsets[i].name.len != len) { + continue; + } + + if (ngx_strncasecmp(charsets[i].name.data, charset->data, len) == 0) { return i; } } @@ -1261,7 +1288,7 @@ ngx_http_set_charset_slot(ngx_conf_t *cf char *p = conf; ngx_int_t *cp; - ngx_str_t *value; + ngx_str_t *value, var; ngx_http_charset_main_conf_t *mcf; cp = (ngx_int_t *) (p + cmd->offset); @@ -1279,6 +1306,22 @@ ngx_http_set_charset_slot(ngx_conf_t *cf return NGX_CONF_OK; } + + if (value[1].data[0] == '$') { + var.len = value[1].len - 1; + var.data = value[1].data + 1; + + *cp = ngx_http_get_variable_index(cf, &var); + + if (*cp == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + *cp += NGX_HTTP_CHARSET_VAR; + + return NGX_CONF_OK; + } + mcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_charset_filter_module); 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 @@ -1826,7 +1826,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf hash.hash = &conf->upstream.hide_headers_hash; hash.key = ngx_hash_key_lc; hash.max_size = 512; - hash.bucket_size = ngx_cacheline_size; + hash.bucket_size = ngx_align(64, ngx_cacheline_size); hash.name = "fastcgi_hide_headers_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c new file mode 100644 --- /dev/null +++ b/src/http/modules/ngx_http_flv_module.c @@ -0,0 +1,255 @@ + +/* + * Copyright (C) Igor Sysoev + */ + +#include +#include +#include + + +static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + +static ngx_command_t ngx_http_flv_commands[] = { + + { ngx_string("flv"), + NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, + ngx_http_flv, + 0, + 0, + NULL }, + + ngx_null_command +}; + + +static u_char ngx_flv_header[] = "FLV\x1\x1\0\0\0\x9\0\0\0\x9"; + + +static ngx_http_module_t ngx_http_flv_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_flv_module = { + NGX_MODULE_V1, + &ngx_http_flv_module_ctx, /* module context */ + ngx_http_flv_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_flv_handler(ngx_http_request_t *r) +{ + u_char *p; + off_t start, len; + ngx_fd_t fd; + ngx_int_t rc; + ngx_uint_t level; + ngx_str_t path; + ngx_err_t err; + ngx_log_t *log; + ngx_buf_t *b; + ngx_chain_t out[2]; + ngx_file_info_t fi; + ngx_pool_cleanup_t *cln; + ngx_pool_cleanup_file_t *clnf; + ngx_http_core_loc_conf_t *clcf; + + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { + return NGX_HTTP_NOT_ALLOWED; + } + + if (r->uri.data[r->uri.len - 1] == '/') { + return NGX_DECLINED; + } + + /* TODO: Win32 */ + if (r->zero_in_uri) { + return NGX_DECLINED; + } + + rc = ngx_http_discard_body(r); + + if (rc != NGX_OK && rc != NGX_AGAIN) { + return rc; + } + + if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + log = r->connection->log; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http flv filename: \"%s\"", path.data); + + cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); + if (cln == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + fd = ngx_open_file(path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); + + if (fd == NGX_INVALID_FILE) { + err = ngx_errno; + + if (err == NGX_ENOENT + || err == NGX_ENOTDIR + || err == NGX_ENAMETOOLONG) + { + level = NGX_LOG_ERR; + rc = NGX_HTTP_NOT_FOUND; + + } else if (err == NGX_EACCES) { + level = NGX_LOG_ERR; + rc = NGX_HTTP_FORBIDDEN; + + } else { + level = NGX_LOG_CRIT; + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { + ngx_log_error(level, log, err, + ngx_open_file_n " \"%s\" failed", path.data); + } + + return rc; + } + + if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, + ngx_fd_info_n " \"%s\" failed", path.data); + + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", path.data); + } + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (!ngx_is_file(&fi)) { + + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", path.data); + } + + return NGX_DECLINED; + } + + start = 0; + len = ngx_file_size(&fi); + + if (r->args.len) { + p = (u_char *) ngx_strstr(r->args.data, "start="); + + if (p) { + p += 6; + + start = ngx_atoof(p, r->args.len - (p - r->args.data)); + + if (start == NGX_ERROR || start >= len) { + start = 0; + } + + len -= start; + } + } + + log->action = "sending flv to client"; + + cln->handler = ngx_pool_cleanup_file; + clnf = cln->data; + + clnf->fd = fd; + clnf->name = path.data; + clnf->log = r->pool->log; + + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.content_length_n = sizeof(ngx_flv_header) - 1 + len; + r->headers_out.last_modified_time = ngx_file_mtime(&fi); + + if (ngx_http_set_content_type(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + if (b == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + b->pos = ngx_flv_header; + b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1; + b->memory = 1; + + out[0].buf = b; + out[0].next = &out[1]; + + b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + if (b == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); + if (b->file == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + return rc; + } + + b->file_pos = start; + b->file_last = ngx_file_size(&fi); + + b->in_file = b->file_last ? 1: 0; + b->last_buf = 1; + b->last_in_chain = 1; + + b->file->fd = fd; + b->file->name = path; + b->file->log = log; + + out[1].buf = b; + out[1].next = NULL; + + return ngx_http_output_filter(r, out); +} + + +static char * +ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + clcf->handler = ngx_http_flv_handler; + + return NGX_CONF_OK; +} diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1823,7 +1823,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t hash.hash = &conf->upstream.hide_headers_hash; hash.key = ngx_hash_key_lc; hash.max_size = 512; - hash.bucket_size = ngx_cacheline_size; + hash.bucket_size = ngx_align(64, ngx_cacheline_size); hash.name = "proxy_hide_headers_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -417,10 +417,11 @@ ngx_http_ssi_body_filter(ngx_http_reques return NGX_AGAIN; } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" continue", &r->uri); - - ctx->wait = 0; + if (ctx->wait == r) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter \"%V\" continue", &r->uri); + ctx->wait = NULL; + } } slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); @@ -1814,6 +1815,7 @@ ngx_http_ssi_include(ngx_http_request_t ngx_buf_t *b; ngx_uint_t flags, i; ngx_chain_t *out, *cl, *tl, **ll; + ngx_http_request_t *sr; ngx_http_ssi_ctx_t *mctx; ngx_http_ssi_block_t *bl; @@ -1936,7 +1938,7 @@ ngx_http_ssi_include(ngx_http_request_t } } - rc = ngx_http_subrequest(r, uri, &args, out, flags); + rc = ngx_http_subrequest(r, uri, &args, &sr, out, flags); if (rc == NGX_ERROR) { return NGX_HTTP_SSI_ERROR; @@ -1947,7 +1949,13 @@ ngx_http_ssi_include(ngx_http_request_t } if (rc == NGX_AGAIN) { - ctx->wait = 1; + if (ctx->wait == NULL) { + ctx->wait = sr; + + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "only one subrequest may be waited at the same time"); + } } return rc; diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h --- a/src/http/modules/ngx_http_ssi_filter_module.h +++ b/src/http/modules/ngx_http_ssi_filter_module.h @@ -63,8 +63,8 @@ typedef struct { unsigned block:1; unsigned output:1; unsigned output_chosen:1; - unsigned wait:1; + ngx_http_request_t *wait; void *value_buf; ngx_str_t timefmt; ngx_str_t errmsg; 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 @@ -365,7 +365,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma hash.hash = &cmcf->headers_in_hash; hash.key = ngx_hash_key_lc; hash.max_size = 512; - hash.bucket_size = ngx_cacheline_size; + hash.bucket_size = ngx_align(64, ngx_cacheline_size); hash.name = "headers_in_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; 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 @@ -1283,7 +1283,8 @@ ngx_http_auth_basic_user(ngx_http_reques ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, - ngx_str_t *uri, ngx_str_t *args, ngx_chain_t *out, ngx_uint_t flags) + ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr, + ngx_chain_t *out, ngx_uint_t flags) { ngx_connection_t *c; ngx_http_request_t *sr; @@ -1417,6 +1418,8 @@ ngx_http_subrequest(ngx_http_request_t * ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http subrequest done \"%V?%V\"", uri, &sr->args); + *psr = sr; + if (sr->fast_subrequest) { sr->fast_subrequest = 0; 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 @@ -305,7 +305,8 @@ u_char *ngx_http_map_uri_to_path(ngx_htt ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r); ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, - ngx_str_t *uri, ngx_str_t *args, ngx_chain_t *out, ngx_uint_t flags); + ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **sr, + ngx_chain_t *out, ngx_uint_t flags); ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args); 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 @@ -1137,6 +1137,7 @@ ngx_http_upstream_process_header(ngx_eve umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); if (r->upstream->headers_in.x_accel_redirect) { + ngx_http_upstream_finalize_request(r, u, NGX_DECLINED); part = &r->upstream->headers_in.headers.part; @@ -1159,8 +1160,8 @@ ngx_http_upstream_process_header(ngx_eve if (hh && hh->redirect) { if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) { - ngx_http_upstream_finalize_request(r, u, - NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_http_finalize_request(r, + NGX_HTTP_INTERNAL_SERVER_ERROR); return; } } @@ -1172,7 +1173,7 @@ ngx_http_upstream_process_header(ngx_eve flags = 0; if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { - ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND); + ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); return; } @@ -1500,6 +1501,8 @@ ngx_http_upstream_process_non_buffered_b ngx_http_core_loc_conf_t *clcf; c = ev->data; + r = c->data; + u = r->upstream; if (ev->write) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, @@ -1520,10 +1523,11 @@ ngx_http_upstream_process_non_buffered_b } else { ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); } + + ngx_http_upstream_finalize_request(r, u, 0); + return; } - r = c->data; - u = r->upstream; client = r->connection; b = &u->buffer; @@ -2941,7 +2945,7 @@ ngx_http_upstream_init_main_conf(ngx_con hash.hash = &umcf->headers_in_hash; hash.key = ngx_hash_key_lc; hash.max_size = 512; - hash.bucket_size = ngx_cacheline_size; + hash.bucket_size = ngx_align(64, ngx_cacheline_size); hash.name = "upstream_headers_in_hash"; hash.pool = cf->pool; hash.temp_pool = NULL; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -50,6 +50,8 @@ static ngx_int_t ngx_http_variable_body_ ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -170,6 +172,10 @@ static ngx_http_variable_t ngx_http_cor ngx_http_variable_request_completion, 0, 0, 0 }, + { ngx_string("request_body_file"), NULL, + ngx_http_variable_request_body_file, + 0, 0, 0 }, + { ngx_string("sent_http_content_type"), NULL, ngx_http_variable_sent_content_type, 0, 0, 0 }, @@ -1134,6 +1140,30 @@ ngx_http_variable_request_completion(ngx } +static ngx_int_t +ngx_http_variable_request_body_file(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->request_body == NULL || r->request_body->temp_file == NULL) { + v->len = 0; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = (u_char *) ""; + + return NGX_OK; + } + + v->len = r->request_body->temp_file->file.name.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = r->request_body->temp_file->file.name.data; + + return NGX_OK; +} + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) { diff --git a/src/os/unix/ngx_sunpro_x86.map b/src/os/unix/ngx_sunpro_x86.map --- a/src/os/unix/ngx_sunpro_x86.map +++ b/src/os/unix/ngx_sunpro_x86.map @@ -1,2 +1,2 @@ # disable { PAUSE ] hwcap for Sun Studio 11 -hwcap_1 = OVERRIDE; +hwcap_1 = OVERRIDE;