diff options
-rw-r--r-- | auto/cc | 4 | ||||
-rw-r--r-- | auto/sources | 1 | ||||
-rw-r--r-- | src/core/nginx.c | 2 | ||||
-rw-r--r-- | src/core/ngx_config.h | 3 | ||||
-rw-r--r-- | src/core/ngx_core.h | 1 | ||||
-rw-r--r-- | src/core/ngx_crc.h | 26 | ||||
-rw-r--r-- | src/core/ngx_log.c | 4 | ||||
-rw-r--r-- | src/core/ngx_log.h | 85 | ||||
-rw-r--r-- | src/http/modules/ngx_http_index_handler.c | 274 | ||||
-rw-r--r-- | src/http/modules/ngx_http_static_handler.c | 510 | ||||
-rw-r--r-- | src/http/ngx_http.c | 20 | ||||
-rw-r--r-- | src/http/ngx_http.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_cache.c | 447 | ||||
-rw-r--r-- | src/http/ngx_http_cache.h | 68 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 458 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.h | 37 | ||||
-rw-r--r-- | src/http/ngx_http_parse.c | 16 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 52 | ||||
-rw-r--r-- | src/http/ngx_http_request.h | 7 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_sendfile_chain.c | 18 | ||||
-rw-r--r-- | src/os/unix/ngx_linux_sendfile_chain.c | 7 |
21 files changed, 1209 insertions, 832 deletions
@@ -24,6 +24,8 @@ case $CC in # debug CFLAGS="$CFLAGS -g" + CFLAGS="$CFLAGS -D HAVE_GCC_VARIADIC_MACROS=1" + OBJEXT=o OBJOUT="-o " BINOUT="-o " @@ -48,6 +50,8 @@ case $CC in # stop on warning CFLAGS="$CFLAGS -Werror" + CFLAGS="$CFLAGS -D HAVE_C99_VARIADIC_MACROS=1" + OBJEXT=o OBJOUT="-o " BINOUT="-o " diff --git a/auto/sources b/auto/sources index f26b9404e..f2f040162 100644 --- a/auto/sources +++ b/auto/sources @@ -14,6 +14,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_parse.h \ src/core/ngx_inet.h \ src/core/ngx_file.h \ + src/core/ngx_crc.h \ src/core/ngx_regex.h \ src/core/ngx_times.h \ src/core/ngx_connection.h \ diff --git a/src/core/nginx.c b/src/core/nginx.c index 77d1dc632..8c4716d68 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -134,7 +134,7 @@ int main(int argc, char *const *argv) /* life cycle */ for ( ;; ) { - /* STUB */ cycle->log->log_level = NGX_LOG_DEBUG; + /* STUB */ cycle->log->log_level = NGX_LOG_DEBUG|NGX_LOG_DEBUG_HTTP; #if 0 diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index ccb653b98..b943960b2 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -38,6 +38,9 @@ typedef int ngx_int_t; typedef u_int ngx_uint_t; +/* STUB: autoconf */ +#define PTR_FMT "%X" + #include <ngx_auto_config.h> diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index 8d096fa89..5b76d86c7 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -28,6 +28,7 @@ typedef struct ngx_connection_s ngx_connection_t; #include <ngx_types.h> #include <ngx_file.h> #include <ngx_files.h> +#include <ngx_crc.h> #include <ngx_regex.h> #include <ngx_times.h> #include <ngx_inet.h> diff --git a/src/core/ngx_crc.h b/src/core/ngx_crc.h new file mode 100644 index 000000000..df6488967 --- /dev/null +++ b/src/core/ngx_crc.h @@ -0,0 +1,26 @@ +#ifndef _NGX_CRC_H_INCLUDED_ +#define _NGX_CRC_H_INCLUDED_ + + +/* 32-bit crc16 */ + +ngx_inline static uint32_t ngx_crc(char *data, size_t len) +{ + uint32_t sum; + + for (sum = 0; len; len--) { + /* + * gcc 2.95.2 x86 and icc 7.1.006 compile that operator + * into the single rol opcode. + * msvc 6.0sp2 compiles it into four opcodes. + */ + sum = sum >> 1 | sum << 31; + + sum += *data++; + } + + return sum; +} + + +#endif /* _NGX_CRC_H_INCLUDED_ */ diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c index 627c507fc..e3e292ced 100644 --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -169,12 +169,12 @@ void ngx_log_error(int level, ngx_log_t *log, ngx_err_t err, } -void ngx_log_debug_core(ngx_log_t *log, const char *fmt, ...) +void ngx_log_debug_core(ngx_log_t *log, ngx_err_t err, const char *fmt, ...) { va_list args; va_start(args, fmt); - ngx_log_error_core(NGX_LOG_DEBUG, log, 0, fmt, args); + ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, args); va_end(args); } diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h index 290b11c46..59ca1f9c4 100644 --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -6,17 +6,17 @@ #include <ngx_core.h> -typedef enum { - NGX_LOG_STDERR = 0, - NGX_LOG_EMERG, - NGX_LOG_ALERT, - NGX_LOG_CRIT, - NGX_LOG_ERR, - NGX_LOG_WARN, - NGX_LOG_NOTICE, - NGX_LOG_INFO, - NGX_LOG_DEBUG -} ngx_log_e; +#define NGX_LOG_STDERR 0 +#define NGX_LOG_EMERG 1 +#define NGX_LOG_ALERT 2 +#define NGX_LOG_CRIT 3 +#define NGX_LOG_ERR 4 +#define NGX_LOG_WARN 5 +#define NGX_LOG_NOTICE 6 +#define NGX_LOG_INFO 7 +#define NGX_LOG_DEBUG 8 + +#define NGX_LOG_DEBUG_HTTP 0x80 /* @@ -71,13 +71,6 @@ struct ngx_log_s { ngx_open_file_t *file; void *data; ngx_log_handler_pt handler; - -#if 0 -/* STUB */ - char *action; - char *context; -/* */ -#endif }; #define MAX_ERROR_STR 2048 @@ -85,6 +78,8 @@ struct ngx_log_s { #define _ , +/*********************************/ + #if (HAVE_GCC_VARIADIC_MACROS) #define HAVE_VARIADIC_MACROS 1 @@ -94,7 +89,7 @@ struct ngx_log_s { #if (NGX_DEBUG) #define ngx_log_debug(log, args...) \ - if (log->log_level == NGX_LOG_DEBUG) \ + if (log->log_level & NGX_LOG_DEBUG) \ ngx_log_error_core(NGX_LOG_DEBUG, log, 0, args) #else #define ngx_log_debug(log, args...) @@ -110,6 +105,7 @@ struct ngx_log_s { void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...); +/*********************************/ #elif (HAVE_C99_VARIADIC_MACROS) @@ -136,13 +132,16 @@ void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err, void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...); +/*********************************/ #else /* NO VARIADIC MACROS */ +#define HAVE_VARIADIC_MACROS 0 + #if (NGX_DEBUG) #define ngx_log_debug(log, text) \ if (log->log_level == NGX_LOG_DEBUG) \ - ngx_log_debug_core(log, text) + ngx_log_debug_core(log, 0, text) #else #define ngx_log_debug(log, text) #endif @@ -158,13 +157,57 @@ void ngx_log_error(int level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...); void ngx_log_error_core(int level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args); -void ngx_log_debug_core(ngx_log_t *log, const char *fmt, ...); +void ngx_log_debug_core(ngx_log_t *log, ngx_err_t err, const char *fmt, ...); void ngx_assert_core(ngx_log_t *log, const char *fmt, ...); #endif /* VARIADIC MACROS */ +/*********************************/ + +#if (HAVE_VARIADIC_MACROS) + +#if (NGX_DEBUG) +#define ngx_log_debug0(level, log, err, fmt) \ + if (log->log_level & level) \ + ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt) +#else +#define ngx_log_debug0(level, log, err, fmt) +#endif + +#if (NGX_DEBUG) +#define ngx_log_debug1(level, log, err, fmt, arg1) \ + if (log->log_level & level) \ + ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, arg1) +#else +#define ngx_log_debug1(level, log, err, fmt, arg1) +#endif + +/*********************************/ + +#else /* NO VARIADIC MACROS */ + +#if (NGX_DEBUG) +#define ngx_log_debug0(level, log, err, fmt) \ + if (log->log_level & level) \ + ngx_log_debug_core(log, err, fmt) +#else +#define ngx_log_debug0(level, log, err, fmt) +#endif + +#if (NGX_DEBUG) +#define ngx_log_debug1(level, log, err, fmt, arg1) \ + if (log->log_level & level) \ + ngx_log_debug_core(log, err, fmt, arg1) +#else +#define ngx_log_debug1(level, log, err, fmt, arg1) +#endif +#endif + + +/*********************************/ + #define ngx_log_alloc_log(pool, log) ngx_palloc(pool, log, sizeof(ngx_log_t)) #define ngx_log_copy_log(new, old) ngx_memcpy(new, old, sizeof(ngx_log_t)) diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c index 43167673c..ee5efd2cb 100644 --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -7,13 +7,17 @@ typedef struct { ngx_array_t indices; size_t max_index_len; - ngx_http_cache_hash_t *cache; -} ngx_http_index_conf_t; + ngx_http_cache_hash_t *index_cache; +} ngx_http_index_loc_conf_t; typedef struct { - int index; - unsigned tested:1; + ngx_int_t index; + char *last; + ngx_str_t path; + ngx_str_t redirect; + ngx_http_cache_t *cache; + unsigned tested:1; } ngx_http_index_ctx_t; @@ -26,8 +30,8 @@ static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, ngx_http_index_ctx_t *ctx, ngx_err_t err); static int ngx_http_index_init(ngx_cycle_t *cycle); -static void *ngx_http_index_create_conf(ngx_conf_t *cf); -static char *ngx_http_index_merge_conf(ngx_conf_t *cf, +static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -43,10 +47,10 @@ static ngx_command_t ngx_http_index_commands[] = { NULL }, { ngx_string("index_cache"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3, ngx_http_set_cache_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_index_conf_t, cache), + offsetof(ngx_http_index_loc_conf_t, index_cache), NULL }, ngx_null_command @@ -62,8 +66,8 @@ ngx_http_module_t ngx_http_index_module_ctx = { NULL, /* create server configuration */ NULL, /* merge server configuration */ - ngx_http_index_create_conf, /* create location configration */ - ngx_http_index_merge_conf /* merge location configration */ + ngx_http_index_create_loc_conf, /* create location configration */ + ngx_http_index_merge_loc_conf /* merge location configration */ }; @@ -89,72 +93,77 @@ ngx_module_t ngx_http_index_module = { int ngx_http_index_handler(ngx_http_request_t *r) { - char *name, *file; - uint32_t crc; - ngx_int_t rc; - ngx_str_t redirect, *index; - ngx_err_t err; - ngx_fd_t fd; - ngx_http_cache_t *cache; - ngx_http_index_ctx_t *ctx; - ngx_http_index_conf_t *ilcf; - ngx_http_core_loc_conf_t *clcf; + char *name; + uint32_t crc; + size_t len; + ngx_fd_t fd; + ngx_int_t rc; + ngx_str_t *index; + ngx_err_t err; + ngx_log_t *log; + ngx_http_index_ctx_t *ctx; + ngx_http_core_loc_conf_t *clcf; + ngx_http_index_loc_conf_t *ilcf; if (r->uri.data[r->uri.len - 1] != '/') { return NGX_DECLINED; } + log = r->connection->log; + + /* + * we use context because the handler supports an async file opening + * and thus can be called several times + */ + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); - if (ilcf->cache) { - cache = ngx_http_cache_get(ilcf->cache, &r->uri, &crc); + ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); + if (ctx == NULL) { + ngx_http_create_ctx(r, ctx, ngx_http_index_module, + sizeof(ngx_http_index_ctx_t), + NGX_HTTP_INTERNAL_SERVER_ERROR); -ngx_log_debug(r->connection->log, "index cache get: %x" _ cache); + if (ilcf->index_cache) { + ctx->cache = ngx_http_cache_get(ilcf->index_cache, NULL, + &r->uri, &crc); - if (cache && ilcf->cache->update >= ngx_cached_time - cache->updated) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http index cache get: " PTR_FMT, ctx->cache); - cache->accessed = ngx_cached_time; + if (ctx->cache && ctx->cache->valid) { - redirect.len = cache->data.value.len; - if (!(redirect.data = ngx_palloc(r->pool, redirect.len + 1))) { - ngx_http_cache_unlock(ilcf->cache, cache, r->connection->log); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } + ctx->cache->accessed = ngx_cached_time; - ngx_memcpy(redirect.data, cache->data.value.data, redirect.len + 1); - ngx_http_cache_unlock(ilcf->cache, cache, r->connection->log); + ctx->redirect.len = ctx->cache->data.value.len; + ctx->redirect.data = ngx_palloc(r->pool, ctx->redirect.len + 1); + if (ctx->redirect.data == NULL) { + ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } - return ngx_http_internal_redirect(r, &redirect, NULL); - } + ngx_memcpy(ctx->redirect.data, ctx->cache->data.value.data, + ctx->redirect.len + 1); + ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log); - } else { - cache = NULL; - } + return ngx_http_internal_redirect(r, &ctx->redirect, NULL); + } - ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); - if (ctx == NULL) { - ngx_http_create_ctx(r, ctx, ngx_http_index_module, - sizeof(ngx_http_index_ctx_t), - NGX_HTTP_INTERNAL_SERVER_ERROR); - } + } else { + ctx->cache = NULL; + } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + len = clcf->doc_root.len + r->uri.len + ilcf->max_index_len; + if (!(ctx->path.data = ngx_palloc(r->pool, len))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } - if (r->path.data == NULL) { - r->path_allocated = clcf->doc_root.len + r->uri.len - + ilcf->max_index_len; - ngx_test_null(r->path.data, - ngx_palloc(r->pool, r->path_allocated), - NGX_HTTP_INTERNAL_SERVER_ERROR); - - redirect.data = ngx_cpymem(r->path.data, clcf->doc_root.data, - clcf->doc_root.len); - file = ngx_cpystrn(redirect.data, r->uri.data, r->uri.len + 1); - r->path.len = file - r->path.data; - - } else{ - redirect.data = r->path.data + r->path.len; - file = redirect.data + r->uri.len; + ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->doc_root.data, + clcf->doc_root.len); + ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data, + r->uri.len + 1); + ctx->path.len = ctx->last - ctx->path.data; } index = ilcf->indices.elts; @@ -164,8 +173,9 @@ ngx_log_debug(r->connection->log, "index cache get: %x" _ cache); name = index[ctx->index].data; } else { - ngx_memcpy(file, index[ctx->index].data, index[ctx->index].len + 1); - name = r->path.data; + ngx_memcpy(ctx->last, index[ctx->index].data, + index[ctx->index].len + 1); + name = ctx->path.data; } fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN); @@ -177,8 +187,8 @@ ngx_log_debug(r->connection->log, "index cache get: %x" _ cache); if (fd == NGX_INVALID_FILE) { err = ngx_errno; -ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err, - "DEBUG: " ngx_open_file_n " %s failed", name); + ngx_log_error(NGX_LOG_DEBUG, log, err, + "debug: " ngx_open_file_n " %s failed", name); if (err == NGX_ENOTDIR) { return ngx_http_index_error(r, ctx, err); @@ -201,80 +211,68 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err, continue; } - ngx_log_error(NGX_LOG_ERR, r->connection->log, err, + ngx_log_error(NGX_LOG_ERR, log, err, ngx_open_file_n " %s failed", name); return NGX_HTTP_INTERNAL_SERVER_ERROR; } + + /* STUB: open file cache */ + r->file.name.data = name; r->file.fd = fd; if (index[ctx->index].data[0] == '/') { r->file.name.len = index[ctx->index].len; - redirect.len = index[ctx->index].len; - redirect.data = index[ctx->index].data; + ctx->redirect.len = index[ctx->index].len; + ctx->redirect.data = index[ctx->index].data; } else { - redirect.len = r->uri.len + index[ctx->index].len; + ctx->redirect.len = r->uri.len + index[ctx->index].len; r->file.name.len = clcf->doc_root.len + r->uri.len + index[ctx->index].len; } - if (ilcf->cache) { + /**/ - if (cache) { - if (redirect.len == cache->data.value.len - && ngx_memcmp(cache->data.value.data, redirect.data, - redirect.len) == 0) - { - cache->accessed = ngx_cached_time; - cache->updated = ngx_cached_time; - ngx_http_cache_unlock(ilcf->cache, cache, - r->connection->log); - - return ngx_http_internal_redirect(r, &redirect, NULL); - - } else { - if (redirect.len > cache->data.value.len) { - ngx_free(cache->data.value.data); - cache->data.value.data = NULL; - } - } - } - if (cache == NULL) { - cache = ngx_http_cache_alloc(ilcf->cache, &r->uri, crc, - r->connection->log); - } + if (ilcf->index_cache) { -ngx_log_debug(r->connection->log, "index cache alloc: %x" _ cache); - - if (cache) { - cache->fd = NGX_INVALID_FILE; - cache->accessed = ngx_cached_time; - cache->last_modified = 0; - cache->updated = ngx_cached_time; - - cache->data.value.len = redirect.len; - if (cache->data.value.data == NULL) { - cache->data.value.data = ngx_alloc(redirect.len + 1, - r->connection->log); - if (cache->data.value.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - } + if (ctx->cache) { + if (ctx->redirect.len == ctx->cache->data.value.len + && ngx_memcmp(ctx->cache->data.value.data, + ctx->redirect.data, ctx->redirect.len) == 0) + { + ctx->cache->accessed = ngx_cached_time; + ctx->cache->updated = ngx_cached_time; + ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log); - ngx_memcpy(cache->data.value.data, redirect.data, - redirect.len + 1); + return ngx_http_internal_redirect(r, &ctx->redirect, NULL); + } } - } - if (cache) { - ngx_http_cache_unlock(ilcf->cache, cache, r->connection->log); + ctx->redirect.len++; + ctx->cache = ngx_http_cache_alloc(ilcf->index_cache, ctx->cache, + NULL, &r->uri, crc, + &ctx->redirect, log); + ctx->redirect.len--; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http index cache alloc: " PTR_FMT, ctx->cache); + + if (ctx->cache) { + ctx->cache->fd = NGX_INVALID_FILE; + ctx->cache->accessed = ngx_cached_time; + ctx->cache->last_modified = 0; + ctx->cache->updated = ngx_cached_time; + ctx->cache->valid = 1; + ctx->cache->memory = 1; + ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log); + } } - return ngx_http_internal_redirect(r, &redirect, NULL); + return ngx_http_internal_redirect(r, &ctx->redirect, NULL); } return NGX_DECLINED; @@ -286,27 +284,27 @@ static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, { ngx_err_t err; - r->path.data[r->path.len - 1] = '\0'; - r->path.data[r->path.len] = '\0'; + ctx->path.data[ctx->path.len - 1] = '\0'; + ctx->path.data[ctx->path.len] = '\0'; -ngx_log_debug(r->connection->log, "IS_DIR: %s" _ r->path.data); +ngx_log_debug(r->connection->log, "IS_DIR: %s" _ ctx->path.data); - if (ngx_file_info(r->path.data, &r->file.info) == -1) { + if (ngx_file_info(ctx->path.data, &r->file.info) == -1) { err = ngx_errno; if (err == NGX_ENOENT) { - r->path.data[r->path.len - 1] = '/'; + ctx->path.data[ctx->path.len - 1] = '/'; return ngx_http_index_error(r, ctx, err); } ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, - ngx_file_info_n " %s failed", r->path.data); + ngx_file_info_n " %s failed", ctx->path.data); return NGX_HTTP_INTERNAL_SERVER_ERROR; } - r->path.data[r->path.len - 1] = '/'; + ctx->path.data[ctx->path.len - 1] = '/'; if (ngx_is_dir(&r->file.info)) { return NGX_OK; @@ -322,13 +320,13 @@ static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, { if (err == NGX_EACCES) { ngx_log_error(NGX_LOG_ERR, r->connection->log, err, - "\"%s\" is forbidden", r->path.data); + "\"%s\" is forbidden", ctx->path.data); return NGX_HTTP_FORBIDDEN; } ngx_log_error(NGX_LOG_ERR, r->connection->log, err, - "\"%s\" is not found", r->path.data); + "\"%s\" is not found", ctx->path.data); return NGX_HTTP_NOT_FOUND; } @@ -342,27 +340,29 @@ static int ngx_http_index_init(ngx_cycle_t *cycle) ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; - ngx_test_null(h, ngx_push_array( - &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), - NGX_ERROR); + h = ngx_push_array(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + *h = ngx_http_index_handler; return NGX_OK; } -static void *ngx_http_index_create_conf(ngx_conf_t *cf) +static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf) { - ngx_http_index_conf_t *conf; + ngx_http_index_loc_conf_t *conf; - ngx_test_null(conf, ngx_palloc(cf->pool, sizeof(ngx_http_index_conf_t)), + ngx_test_null(conf, ngx_palloc(cf->pool, sizeof(ngx_http_index_loc_conf_t)), NGX_CONF_ERROR); ngx_init_array(conf->indices, cf->pool, 3, sizeof(ngx_str_t), NGX_CONF_ERROR); conf->max_index_len = 0; - conf->cache = NULL; + conf->index_cache = NULL; return conf; } @@ -370,18 +370,18 @@ static void *ngx_http_index_create_conf(ngx_conf_t *cf) /* TODO: remove duplicate indices */ -static char *ngx_http_index_merge_conf(ngx_conf_t *cf, - void *parent, void *child) +static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child) { - ngx_http_index_conf_t *prev = parent; - ngx_http_index_conf_t *conf = child; + ngx_http_index_loc_conf_t *prev = parent; + ngx_http_index_loc_conf_t *conf = child; int i; ngx_str_t *index, *prev_index; if (conf->max_index_len == 0) { if (prev->max_index_len != 0) { - ngx_memcpy(conf, prev, sizeof(ngx_http_index_conf_t)); + ngx_memcpy(conf, prev, sizeof(ngx_http_index_loc_conf_t)); return NGX_CONF_OK; } @@ -408,8 +408,8 @@ static char *ngx_http_index_merge_conf(ngx_conf_t *cf, conf->max_index_len = prev->max_index_len; } - if (conf->cache == NULL) { - conf->cache = prev->cache; + if (conf->index_cache == NULL) { + conf->index_cache = prev->index_cache; } return NGX_CONF_OK; @@ -421,7 +421,7 @@ static char *ngx_http_index_merge_conf(ngx_conf_t *cf, static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_index_conf_t *ilcf = conf; + ngx_http_index_loc_conf_t *ilcf = conf; int i; ngx_str_t *index, *value; diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c index 1be269770..1c754a050 100644 --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -4,13 +4,28 @@ #include <ngx_http.h> -static int ngx_http_static_handler(ngx_http_request_t *r); -static int ngx_http_static_init(ngx_cycle_t *cycle); +typedef struct { + ngx_http_cache_hash_t *redirect_cache; +} ngx_http_static_loc_conf_t; + + +static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r); +static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); +static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle); static ngx_command_t ngx_http_static_commands[] = { - ngx_null_command + { ngx_string("redirect_cache"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3, + ngx_http_set_cache_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_static_loc_conf_t, redirect_cache), + NULL }, + + ngx_null_command }; @@ -24,8 +39,8 @@ ngx_http_module_t ngx_http_static_module_ctx = { NULL, /* create server configuration */ NULL, /* merge server configuration */ - NULL, /* create location configuration */ - NULL /* merge location configuration */ + ngx_http_static_create_loc_conf, /* create location configuration */ + ngx_http_static_merge_loc_conf /* merge location configuration */ }; @@ -39,86 +54,149 @@ ngx_module_t ngx_http_static_module = { }; -ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) +static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r) { - char *location, *last, *path; - uint32_t crc; - ngx_int_t rc, level; - ngx_str_t name; - ngx_err_t err; - ngx_http_cache_t *cache; - ngx_http_cache_conf_t *ccf; - ngx_http_core_loc_conf_t *clcf; + char *last; + uint32_t file_crc, redirect_crc; + ngx_fd_t fd; + ngx_int_t rc, level; + ngx_str_t name, location; + ngx_err_t err; + ngx_log_t *log; + ngx_hunk_t *h; + ngx_chain_t out; + ngx_file_info_t fi; + ngx_http_cache_t *file, *redirect; + ngx_http_cleanup_t *file_cleanup, *redirect_cleanup; + ngx_http_log_ctx_t *ctx; + ngx_http_core_loc_conf_t *clcf; + ngx_http_static_loc_conf_t *slcf; + + if (r->uri.data[r->uri.len - 1] == '/') { + return NGX_DECLINED; + } if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } + rc = ngx_http_discard_body(r); + + if (rc != NGX_OK) { + return rc; + } + + /* + * there is a valid cached open file, i.e by index handler, + * and it must be already registered in r->cleanup + */ + + if (r->cache && r->cache->valid) { + return ngx_http_send_cached(r); + } + + log = r->connection->log; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + /* + * make a file name + * 2 bytes is for a trailing '/' in a possible redirect and for '\0' + */ - if (r->uri.data[r->uri.len - 1] == '/') { + ngx_test_null(name.data, + ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + location.data = ngx_cpymem(name.data, clcf->doc_root.data, + clcf->doc_root.len); + last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1); + name.len = last - name.data; + location.len = last - location.data + 1; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http filename: \"%s\"", name.data); - /* there is no index handler */ - if (!(path = ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len))) { + /* allocate cleanups */ + + if (!(file_cleanup = ngx_push_array(&r->cleanup))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + file_cleanup->valid = 0; + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module); + if (slcf->redirect_cache) { + if (!(redirect_cleanup = ngx_push_array(&r->cleanup))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } + redirect_cleanup->valid = 0; - ngx_cpystrn(ngx_cpymem(path, clcf->doc_root.data, clcf->doc_root.len), - r->uri.data, r->uri.len + 1); + } else { + redirect_cleanup = NULL; + } - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "directory index of \"%s\" is forbidden", path); - return NGX_HTTP_FORBIDDEN; - } + /* look up an open files cache */ + if (clcf->open_files) { + file = ngx_http_cache_get(clcf->open_files, file_cleanup, + &name, &file_crc); - /* "+ 2" is for a trailing '/' in a possible redirect and '\0' */ - ngx_test_null(name.data, - ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len + 2), - NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http open file cache get: " PTR_FMT, file); - location = ngx_cpymem(name.data, clcf->doc_root.data, clcf->doc_root.len); - last = ngx_cpystrn(location, r->uri.data, r->uri.len + 1); + if (file && file->valid) { + r->cache = file; + return ngx_http_send_cached(r); + } - ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ data); + } else { + file = NULL; + } - if (r->cache == NULL) { + /* look up an redirect cache */ - /* look up an open files cache */ + if (slcf->redirect_cache) { + redirect = ngx_http_cache_get(slcf->redirect_cache, redirect_cleanup, + &name, &redirect_crc); - ccf = ngx_http_get_module_loc_conf(r, ngx_http_cache_module); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http redirect cache get: " PTR_FMT, redirect); - if (ccf->open_files) { - cache = ngx_http_cache_get(ccf->open_files, &name, &crc); + if (redirect && redirect->valid) { - ngx_log_debug(r->connection->log, "cache get: %x" _ cache); + /* + * We do not copy a cached value so the cache entry is locked + * until the end of the request. In a single threaded model + * the redirected request should complete before other event + * will be processed. In a multithreaded model this locking + * should keep more popular redirects in cache. + */ - if (cache - && ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) - || ccf->open_files->update - >= ngx_cached_time - cache->updated)) + if (!(r->headers_out.location = + ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) { - r->cache = cache; - r->content_handler = ngx_http_static_handler; - - return NGX_OK; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } - } else { - cache = NULL; + r->headers_out.location->value = redirect->data.value; + + return NGX_HTTP_MOVED_PERMANENTLY; } } else { - cache = r->cache; + redirect = NULL; } + /* open file */ + #if (WIN9X) + /* TODO: redirect cache */ + if (ngx_win32_version < NGX_WIN_NT) { /* @@ -127,9 +205,9 @@ ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) * so we need to check its type before the opening */ - if (ngx_file_info(name.data, &r->file.info) == NGX_FILE_ERROR) { + if (ngx_file_info(name.data, &fi) == NGX_FILE_ERROR) { err = ngx_errno; - ngx_log_error(NGX_LOG_ERR, r->connection->log, err, + ngx_log_error(NGX_LOG_ERR, log, err, ngx_file_info_n " \"%s\" failed", name.data); if (err == NGX_ENOENT || err == NGX_ENOTDIR) { @@ -143,8 +221,8 @@ ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) } } - if (ngx_is_dir(&r->file.info)) { - ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ name.data); + if (ngx_is_dir(&fi)) { + ngx_log_debug(log, "HTTP DIR: '%s'" _ name.data); if (!(r->headers_out.location = ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) @@ -154,8 +232,6 @@ ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) *last++ = '/'; *last = '\0'; - r->headers_out.location->key.len = 8; - r->headers_out.location->key.data = "Location" ; r->headers_out.location->value.len = last - location; r->headers_out.location->value.data = location; @@ -166,12 +242,9 @@ ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) #endif - if (r->file.fd == NGX_INVALID_FILE) { - r->file.fd = ngx_open_file(r->file.name.data, - NGX_FILE_RDONLY, NGX_FILE_OPEN); - } + fd = ngx_open_file(name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); - if (r->file.fd == NGX_INVALID_FILE) { + if (fd == NGX_INVALID_FILE) { err = ngx_errno; if (err == NGX_ENOENT || err == NGX_ENOTDIR) { @@ -187,60 +260,37 @@ ngx_int_t ngx_http_static_translate_handler(ngx_http_request_t *r) rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } - ngx_log_error(level, r->connection->log, ngx_errno, - ngx_open_file_n " \"%s\" failed", r->file.name.data); + ngx_log_error(level, log, err, + ngx_open_file_n " \"%s\" failed", name.data); return rc; } -ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd); - - if (!r->file.info_valid) { - if (ngx_fd_info(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - ngx_fd_info_n " \"%s\" failed", r->file.name.data); - - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - r->file.name.data); - } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", fd); - r->file.fd = NGX_INVALID_FILE; + if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, + ngx_fd_info_n " \"%s\" failed", name.data); - return NGX_HTTP_INTERNAL_SERVER_ERROR; + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", name.data); } - r->file.info_valid = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (ccf->open_files) { - if (cache == NULL) { - cache = ngx_http_cache_alloc(ccf->open_files, &r->file.name, crc, - r->connection->log); - } - -ngx_log_debug(r->connection->log, "cache alloc: %x" _ cache); + if (ngx_is_dir(&fi)) { - if (cache) { - cache->fd = r->file.fd; - cache->data.size = ngx_file_size(&r->file.info); - cache->accessed = ngx_time(); - cache->last_modified = ngx_file_mtime(&r->file.info); - cache->updated = ngx_time(); - } - } + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir"); - if (ngx_is_dir(&r->file.info)) { -ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); - - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", r->file.name.data); + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", name.data); } - r->file.fd = NGX_INVALID_FILE; - r->file.info_valid = 0; + *last++ = '/'; + *last = '\0'; if (!(r->headers_out.location = ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) @@ -248,152 +298,151 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data); return NGX_HTTP_INTERNAL_SERVER_ERROR; } - *last++ = '/'; - *last = '\0'; -#if 0 - r->headers_out.location->key.len = 8; - r->headers_out.location->key.data = "Location" ; -#endif - r->headers_out.location->value.len = last - location; - r->headers_out.location->value.data = location; + r->headers_out.location->value = location; - return NGX_HTTP_MOVED_PERMANENTLY; - } - -#if !(WIN32) /* the not regular files are probably Unix specific */ + if (slcf->redirect_cache) { + if (redirect) { + if (location.len == redirect->data.value.len + && ngx_memcmp(redirect->data.value.data, location.data, + location.len) == 0) + { + redirect->accessed = ngx_cached_time; + redirect->updated = ngx_cached_time; - if (!ngx_is_file(&r->file.info)) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - "%s is not a regular file", r->file.name.data); + /* + * we can unlock the cache entry because + * we have the local copy anyway + */ - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_file_n " %s failed", r->file.name.data); + ngx_http_cache_unlock(slcf->redirect_cache, redirect, log); + redirect_cleanup->valid = 0; - return NGX_HTTP_NOT_FOUND; - } + return NGX_HTTP_MOVED_PERMANENTLY; + } + } -#endif + location.len++; + redirect = ngx_http_cache_alloc(slcf->redirect_cache, redirect, + redirect_cleanup, + &name, redirect_crc, + &location, log); + location.len--; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http redirect cache alloc: " PTR_FMT, redirect); + + if (redirect) { + redirect->fd = NGX_INVALID_FILE; + redirect->accessed = ngx_cached_time; + redirect->last_modified = 0; + redirect->updated = ngx_cached_time; + redirect->valid = 1; + redirect->memory = 1; + ngx_http_cache_unlock(slcf->redirect_cache, redirect, log); + redirect_cleanup->valid = 0; + } - r->content_handler = ngx_http_static_handler; + } - return NGX_OK; -} + return NGX_HTTP_MOVED_PERMANENTLY; + } +#if !(WIN32) /* the not regular files are probably Unix specific */ -static int ngx_http_static_handler(ngx_http_request_t *r) -{ - int rc, key, i; - ngx_log_e level; - ngx_err_t err; - ngx_hunk_t *h; - ngx_chain_t out; - ngx_http_type_t *type; - ngx_http_cleanup_t *cleanup; - ngx_http_log_ctx_t *ctx; - ngx_http_core_loc_conf_t *clcf; + if (!ngx_is_file(&fi)) { + ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, + "%s is not a regular file", name.data); - rc = ngx_http_discard_body(r); + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", name.data); + } - if (rc != NGX_OK) { - return rc; + return NGX_HTTP_NOT_FOUND; } - ctx = r->connection->log->data; - ctx->action = "sending response to client"; - - if (!(cleanup = ngx_push_array(&r->cleanup))) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } +#endif - if (r->file.fd == NGX_INVALID_FILE) { - r->file.fd = ngx_open_file(r->file.name.data, - NGX_FILE_RDONLY, NGX_FILE_OPEN); - if (r->file.fd == NGX_INVALID_FILE) { - err = ngx_errno; + if (clcf->open_files) { - if (err == NGX_ENOENT || err == NGX_ENOTDIR) { - level = NGX_LOG_ERR; - rc = NGX_HTTP_NOT_FOUND; +#if (NGX_USE_HTTP_FILE_CACHE_UNIQ) - } else { - level = NGX_LOG_CRIT; - rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + if (file && file->uniq == ngx_file_uniq(&fi)) { + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", name.data); } + file->accessed = ngx_cached_time; + file->updated = ngx_cached_time; + file->valid = 1; + r->cache = file; - ngx_log_error(level, r->connection->log, ngx_errno, - ngx_open_file_n " %s failed", r->file.name.data); - return rc; - } - } - - cleanup->data.file.fd = r->file.fd; - cleanup->data.file.name = r->file.name.data; - cleanup->cache = 0; + return ngx_http_send_cached(r); - if (!r->file.info_valid) { - if (ngx_fd_info(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - ngx_fd_info_n " %s failed", r->file.name.data); - - if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, - ngx_close_file_n " %s failed", r->file.name.data); + } else { + if (file) { + ngx_http_cache_unlock(clcf->open_files, file, log); + file = NULL; + } - return NGX_HTTP_INTERNAL_SERVER_ERROR; + file = ngx_http_cache_alloc(clcf->open_files, file, + file_cleanup, + &name, file_crc, NULL, log); + if (file) { + file->uniq = ngx_file_uniq(&fi); + } } - r->file.info_valid = 1; - } +#else + file = ngx_http_cache_alloc(clcf->open_files, file, + file_cleanup, + &name, file_crc, NULL, log); +#endif - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = ngx_file_size(&r->file.info); - r->headers_out.last_modified_time = ngx_file_mtime(&r->file.info); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http open file cache alloc: " PTR_FMT, file); + + if (file) { + file->fd = fd; + file->data.size = ngx_file_size(&fi); + file->accessed = ngx_cached_time; + file->last_modified = ngx_file_mtime(&fi); + file->updated = ngx_cached_time; + file->valid = 1; + r->cache = file; + } - if (!(r->headers_out.content_type = - ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) - { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return ngx_http_send_cached(r); } - r->headers_out.content_type->key.len = 0; - r->headers_out.content_type->key.data = NULL; - r->headers_out.content_type->value.len = 0; - r->headers_out.content_type->value.data = NULL; - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (r->exten.len) { - ngx_http_types_hash_key(key, r->exten); + ctx = log->data; + ctx->action = "sending response to client"; - type = (ngx_http_type_t *) clcf->types[key].elts; - for (i = 0; i < clcf->types[key].nelts; i++) { - if (r->exten.len != type[i].exten.len) { - continue; - } + file_cleanup->data.file.fd = fd; + file_cleanup->data.file.name = name.data; + file_cleanup->valid = 1; + file_cleanup->cache = 0; - if (ngx_strcasecmp(r->exten.data, type[i].exten.data) == 0) { - r->headers_out.content_type->value.len = type[i].type.len; - r->headers_out.content_type->value.data = type[i].type.data; + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.content_length_n = ngx_file_size(&fi); + r->headers_out.last_modified_time = ngx_file_mtime(&fi); - break; - } - } + if (ngx_http_set_content_type(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (r->headers_out.content_type->value.len == 0) { - r->headers_out.content_type->value.len = clcf->default_type.len; - r->headers_out.content_type->value.data = clcf->default_type.data; - } /* we need to allocate all before the header would be sent */ - ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), - NGX_HTTP_INTERNAL_SERVER_ERROR); + if (!(h = ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } - ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)), - NGX_HTTP_INTERNAL_SERVER_ERROR); + if (!(h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } rc = ngx_http_send_header(r); @@ -404,10 +453,10 @@ static int ngx_http_static_handler(ngx_http_request_t *r) h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST; h->file_pos = 0; - h->file_last = ngx_file_size(&r->file.info); + h->file_last = ngx_file_size(&fi); - h->file->fd = r->file.fd; - h->file->log = r->connection->log; + h->file->fd = fd; + h->file->log = log; out.hunk = h; out.next = NULL; @@ -416,7 +465,35 @@ static int ngx_http_static_handler(ngx_http_request_t *r) } -static int ngx_http_static_init(ngx_cycle_t *cycle) +static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_static_loc_conf_t *conf; + + if (!(conf = ngx_palloc(cf->pool, sizeof(ngx_http_static_loc_conf_t)))) { + return NGX_CONF_ERROR; + } + + conf->redirect_cache = NULL; + + return conf; +} + + +static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child) +{ + ngx_http_static_loc_conf_t *prev = parent; + ngx_http_static_loc_conf_t *conf = child; + + if (conf->redirect_cache == NULL) { + conf->redirect_cache = prev->redirect_cache; + } + + return NGX_CONF_OK; +} + + +static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle) { ngx_http_handler_pt *h; ngx_http_conf_ctx_t *ctx; @@ -425,11 +502,12 @@ static int ngx_http_static_init(ngx_cycle_t *cycle) ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index]; cmcf = ctx->main_conf[ngx_http_core_module.ctx_index]; - ngx_test_null(h, ngx_push_array( - &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers), - NGX_ERROR); - *h = ngx_http_static_translate_handler; + h = ngx_push_array(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_static_handler; return NGX_OK; } - diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 14ee3eab2..91fa2310b 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -51,6 +51,7 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_listening_t *ls; ngx_http_module_t *module; ngx_conf_t pcf; + ngx_http_handler_pt *h; ngx_http_conf_ctx_t *ctx; ngx_http_in_port_t *in_port, *inport; ngx_http_in_addr_t *in_addr, *inaddr; @@ -219,17 +220,24 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_init_array(cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); - cmcf->phases[NGX_HTTP_REWRITE_PHASE].type = NGX_OK; - cmcf->phases[NGX_HTTP_REWRITE_PHASE].post_handler = - ngx_http_find_location_config; - ngx_init_array(cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers, - cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), + ngx_init_array(cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers, + cf->cycle->pool, 1, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); + cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].type = NGX_OK; + + ngx_test_null(h, ngx_push_array( + &cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers), + NGX_CONF_ERROR); + *h = ngx_http_find_location_config; - cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].type = NGX_OK; + + ngx_init_array(cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, + cf->cycle->pool, 10, sizeof(ngx_http_handler_pt), + NGX_CONF_ERROR); + cmcf->phases[NGX_HTTP_CONTENT_PHASE].type = NGX_OK; /* create the lists of the ports, the addresses and the server names diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 31fa40df8..58d918b36 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -7,6 +7,7 @@ #include <ngx_garbage_collector.h> typedef struct ngx_http_request_s ngx_http_request_t; +typedef struct ngx_http_cleanup_s ngx_http_cleanup_t; #include <ngx_http_cache.h> #include <ngx_http_request.h> diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c index af38e7f31..89f405e96 100644 --- a/src/http/ngx_http_cache.c +++ b/src/http/ngx_http_cache.c @@ -13,13 +13,6 @@ #endif -static int ngx_crc(char *data, size_t len); - -static void *ngx_http_cache_create_conf(ngx_conf_t *cf); -static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, - void *parent, void *child); - - static ngx_http_module_t ngx_http_cache_module_ctx = { NULL, /* pre conf */ @@ -29,8 +22,8 @@ static ngx_http_module_t ngx_http_cache_module_ctx = { NULL, /* create server configuration */ NULL, /* merge server configuration */ - ngx_http_cache_create_conf, /* create location configuration */ - ngx_http_core_merge_loc_conf /* merge location configuration */ + NULL, /* create location configuration */ + NULL /* merge location configuration */ }; @@ -44,43 +37,8 @@ ngx_module_t ngx_http_cache_module = { }; - -int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) -{ - MD5_CTX md5; - - /* we use offsetof() because sizeof() pads struct size to int size */ - ctx->header_size = offsetof(ngx_http_cache_header_t, key) - + ctx->key.len + 1; - - ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32; - if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) { - return NGX_ERROR; - } - - ngx_memcpy(ctx->file.name.data, ctx->path->name.data, ctx->path->name.len); - - MD5Init(&md5); - MD5Update(&md5, (u_char *) ctx->key.data, ctx->key.len); - MD5Final(ctx->md5, &md5); - - ngx_md5_text(ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len, - ctx->md5); - -ngx_log_debug(r->connection->log, "URL: %s, md5: %s" _ ctx->key.data _ - ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len); - - ngx_create_hashed_filename(&ctx->file, ctx->path); - -ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data); - - /* TODO: look open files cache */ - - return ngx_http_cache_open_file(ctx, 0); -} - - -ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache, +ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *hash, + ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t *crc) { ngx_uint_t i; @@ -88,91 +46,185 @@ ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache, *crc = ngx_crc(key->data, key->len); - c = cache->elts + *crc % cache->hash * cache->nelts; + c = hash->elts + *crc % hash->hash * hash->nelts; - ngx_mutex_lock(&cache->mutex); + ngx_mutex_lock(&hash->mutex); - for (i = 0; i < cache->nelts; i++) { + for (i = 0; i < hash->nelts; i++) { if (c[i].crc == *crc && c[i].key.len == key->len && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0) { c[i].refs++; - ngx_mutex_unlock(&cache->mutex); + ngx_mutex_unlock(&hash->mutex); + + if (c[i].notify) { + if (!(ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)) { + c[i].valid = 0; + } + + } else if (ngx_cached_time - c[i].updated >= hash->update) { + c[i].valid = 0; + } + + if (cleanup) { + cleanup->data.cache.hash = hash; + cleanup->data.cache.cache = &c[i]; + cleanup->valid = 1; + cleanup->cache = 1; + } + return &c[i]; } } - ngx_mutex_unlock(&cache->mutex); + ngx_mutex_unlock(&hash->mutex); return NULL; } -ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *cache, +ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *hash, + ngx_http_cache_t *cache, + ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t crc, - ngx_log_t *log) + ngx_str_t *value, ngx_log_t *log) { time_t old; ngx_uint_t i; - ngx_http_cache_t *c, *found; + ngx_http_cache_t *c; old = ngx_cached_time + 1; - found = NULL; - c = cache->elts + crc % cache->hash * cache->nelts; + c = hash->elts + crc % hash->hash * hash->nelts; - ngx_mutex_lock(&cache->mutex); + ngx_mutex_lock(&hash->mutex); - for (i = 0; i < cache->nelts; i++) { - if (c[i].refs > 0) { - /* a busy entry */ - continue; - } + if (cache == NULL) { - if (c[i].key.data == NULL) { - /* a free entry is found */ - found = &c[i]; - break; - } + /* allocate a new entry */ + + for (i = 0; i < hash->nelts; i++) { + if (c[i].refs > 0) { + /* a busy entry */ + continue; + } + + if (c[i].key.len == 0) { + /* a free entry is found */ + cache = &c[i]; + break; + } - /* looking for the oldest cache entry */ + /* looking for the oldest cache entry */ - if (old > c[i].accessed) { + if (old > c[i].accessed) { - old = c[i].accessed; - found = &c[i]; + old = c[i].accessed; + cache = &c[i]; + } } - } - if (found) { - if (found->key.data) { - if (key->len > found->key.len) { - ngx_free(found->key.data); - found->key.data = NULL; + if (cache == NULL) { + ngx_mutex_unlock(&hash->mutex); + return NULL; + } + + ngx_http_cache_free(cache, key, value, log); + + if (cache->key.data == NULL) { + cache->key.data = ngx_alloc(key->len, log); + if (cache->key.data == NULL) { + ngx_http_cache_free(cache, NULL, NULL, log); + ngx_mutex_unlock(&hash->mutex); + return NULL; } } - if (found->key.data == NULL) { - found->key.data = ngx_alloc(key->len, log); - if (found->key.data == NULL) { - ngx_mutex_unlock(&cache->mutex); + cache->key.len = key->len; + ngx_memcpy(cache->key.data, key->data, key->len); + + } else if (value) { + ngx_http_cache_free(cache, key, value, log); + } + + if (value) { + if (cache->data.value.data == NULL) { + cache->data.value.data = ngx_alloc(value->len, log); + if (cache->data.value.data == NULL) { + ngx_http_cache_free(cache, NULL, NULL, log); + ngx_mutex_unlock(&hash->mutex); return NULL; } } - ngx_memcpy(found->key.data, key->data, key->len); + cache->data.value.len = value->len; + ngx_memcpy(cache->data.value.data, value->data, value->len); + } - found->crc = crc; - found->key.len = key->len; - found->refs = 1; - found->count = 0; - found->deleted = 0; + cache->crc = crc; + cache->key.len = key->len; + + cache->refs = 1; + cache->count = 0; + + cache->valid = 1; + cache->deleted = 0; + cache->memory = 0; + cache->mmap = 0; + cache->notify = 0; + + if (cleanup) { + cleanup->data.cache.hash = hash; + cleanup->data.cache.cache = cache; + cleanup->valid = 1; + cleanup->cache = 1; } - ngx_mutex_unlock(&cache->mutex); + ngx_mutex_unlock(&hash->mutex); - return found; + return cache; +} + + +void ngx_http_cache_free(ngx_http_cache_t *cache, + ngx_str_t *key, ngx_str_t *value, ngx_log_t *log) +{ + if (cache->memory) { + if (cache->data.value.data + && (value == NULL || value->len > cache->data.value.len)) + { + ngx_free(cache->data.value.data); + cache->data.value.data = NULL; + } + } + + /* TODO: mmap */ + + cache->data.value.len = 0; + + if (cache->fd != NGX_INVALID_FILE) { + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, + "http cache close fd: %d", cache->fd); + + if (ngx_close_file(cache->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", + cache->key.data); + } + + cache->fd = NGX_INVALID_FILE; + } + + if (cache->key.data && (key == NULL || key->len > cache->key.len)) { + ngx_free(cache->key.data); + cache->key.data = NULL; + } + + cache->key.len = 0; + + cache->refs = 0; } @@ -184,21 +236,85 @@ void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash, cache->refs--; if (cache->refs == 0 && cache->deleted) { -ngx_log_debug(log, "CLOSE FILE: %d" _ cache->fd); - if (cache->fd != NGX_INVALID_FILE) { - if (ngx_close_file(cache->fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - cache->key.data); - } - } - cache->key.data = NULL; + ngx_http_cache_free(cache, NULL, NULL, log); } ngx_mutex_unlock(&hash->mutex); } +#if 0 + +ngx_add_file_event(ngx_fd_t, ngx_event_handler_pt *handler, void *data) +{ + ngx_event_t *ev; + + ev = &ngx_cycle->read_events[fd]; + ngx_memzero(ev, sizeof(ngx_event_t); + + ev->data = data; + ev->event_handler = handler; + + return ngx_add_event(ev, NGX_VNODE_EVENT, 0); +} + + +void ngx_http_cache_invalidate(ngx_event_t *ev) +{ + ngx_http_cache_ctx_t *ctx; + + ctx = ev->data; + + ngx_http_cache_lock(&ctx->hash->mutex); + + if (ctx->cache->refs == 0) + ngx_http_cache_free(ctx->cache, NULL, NULL, ctx->log); + + } else { + ctx->cache->deleted = 1; + } + + ngx_http_cache_unlock(&ctx->hash->mutex); +} + +#endif + + +int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx) +{ + MD5_CTX md5; + + /* we use offsetof() because sizeof() pads struct size to int size */ + ctx->header_size = offsetof(ngx_http_cache_header_t, key) + + ctx->key.len + 1; + + ctx->file.name.len = ctx->path->name.len + 1 + ctx->path->len + 32; + if (!(ctx->file.name.data = ngx_palloc(r->pool, ctx->file.name.len + 1))) { + return NGX_ERROR; + } + + ngx_memcpy(ctx->file.name.data, ctx->path->name.data, ctx->path->name.len); + + MD5Init(&md5); + MD5Update(&md5, (u_char *) ctx->key.data, ctx->key.len); + MD5Final(ctx->md5, &md5); + + ngx_md5_text(ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len, + ctx->md5); + +ngx_log_debug(r->connection->log, "URL: %s, md5: %s" _ ctx->key.data _ + ctx->file.name.data + ctx->path->name.len + 1 + ctx->path->len); + + ngx_create_hashed_filename(&ctx->file, ctx->path); + +ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data); + + /* TODO: look open files cache */ + + return ngx_http_cache_open_file(ctx, 0); +} + + int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq) { ssize_t n; @@ -331,6 +447,57 @@ int ngx_http_cache_update_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx, } +/* TODO: currently fd only */ + +ngx_int_t ngx_http_send_cached(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_hunk_t *h; + ngx_chain_t out; + ngx_http_log_ctx_t *ctx; + + ctx = r->connection->log->data; + ctx->action = "sending response to client"; + + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.content_length_n = r->cache->data.size; + r->headers_out.last_modified_time = r->cache->last_modified; + + if (ngx_http_set_content_type(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + /* we need to allocate all before the header would be sent */ + + if (!(h = ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (!(h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + return rc; + } + + h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST; + + h->file_pos = 0; + h->file_last = ngx_file_size(&r->file.info); + + h->file->fd = r->cache->fd; + h->file->log = r->connection->log; + + out.hunk = h; + out.next = NULL; + + return ngx_http_output_filter(r, &out); +} + + int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, ngx_dir_t *dir) { @@ -375,85 +542,13 @@ int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, } -/* 32-bit crc16 */ - -static int ngx_crc(char *data, size_t len) -{ - uint32_t sum; - - for (sum = 0; len; len--) { - /* - * gcc 2.95.2 x86 and icc 7.1.006 compile that operator - * into the single rol opcode. - * msvc 6.0sp2 compiles it into four opcodes. - */ - sum = sum >> 1 | sum << 31; - - sum += *data++; - } - - return sum; -} - - -static void *ngx_http_cache_create_conf(ngx_conf_t *cf) -{ - ngx_http_cache_conf_t *conf; - - if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_conf_t)))) { - return NGX_CONF_ERROR; - } - - return conf; -} - - -static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, - void *parent, void *child) -{ - ngx_http_cache_conf_t *prev = parent; - ngx_http_cache_conf_t *conf = child; - - if (conf->open_files == NULL) { - conf->open_files = prev->open_files; - } - -#if 0 - if (conf->open_files == NULL) { - if (prev->open_files) { - conf->open_files = prev->open_files; - - } else { - conf->open_files = ngx_pcalloc(cf->pool, - sizeof(ngx_http_cache_hash_t)); - if (conf->open_files == NULL) { - return NGX_CONF_ERROR; - } - - conf->open_files->hash = NGX_HTTP_CACHE_HASH; - conf->open_files->nelts = NGX_HTTP_CACHE_NELTS; - - conf->open_files->elts = ngx_pcalloc(cf->pool, - NGX_HTTP_CACHE_HASH - * NGX_HTTP_CACHE_NELTS - * sizeof(ngx_http_cache_t)); - if (conf->open_files->elts == NULL) { - return NGX_CONF_ERROR; - } - } - } -#endif - - return NGX_CONF_OK; -} - - char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; - ngx_int_t i, dup, invalid; + ngx_int_t i, j, dup, invalid; ngx_str_t *value, line; + ngx_http_cache_t *c; ngx_http_cache_hash_t *ch, **chp; chp = (ngx_http_cache_hash_t **) (p + cmd->offset); @@ -566,5 +661,13 @@ char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + for (i = 0; i < (ngx_int_t) ch->hash; i++) { + c = ch->elts + i * ch->nelts; + + for (j = 0; j < (ngx_int_t) ch->nelts; j++) { + c[j].fd = NGX_INVALID_FILE; + } + } + return NGX_CONF_OK; } diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index feaecd48e..b2088a06e 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -7,22 +7,37 @@ #include <ngx_http.h> +/* + * The 7 uses before an allocation. + * We can use maximum 7 bits, i.e up to the 127 uses. + */ +#define NGX_HTTP_CACHE_LAZY_ALLOCATION_BITS 3 + typedef struct { - uint32_t crc; - ngx_str_t key; - time_t accessed; + uint32_t crc; + ngx_str_t key; + time_t accessed; + + unsigned refs:20; /* 1048576 references */ + + unsigned count:NGX_HTTP_CACHE_LAZY_ALLOCATION_BITS; - unsigned refs:20; /* 1048576 references */ - unsigned count:2; /* lazy allocation: the 4 uses */ - unsigned deleted:1; + unsigned valid:1; + unsigned deleted:1; + unsigned memory:1; + unsigned mmap:1; + unsigned notify:1; - ngx_fd_t fd; - time_t last_modified; - time_t updated; + ngx_fd_t fd; +#if (NGX_USE_HTTP_FILE_CACHE_UNIQ) + ngx_file_uniq_t uniq; /* no needed with kqueue */ +#endif + time_t last_modified; + time_t updated; union { - off_t size; - ngx_str_t value; + off_t size; + ngx_str_t value; } data; } ngx_http_cache_t; @@ -69,30 +84,33 @@ typedef struct { } ngx_http_cache_ctx_t; -typedef struct { - ngx_http_cache_hash_t *open_files; -} ngx_http_cache_conf_t; - - #define NGX_HTTP_CACHE_STALE 1 #define NGX_HTTP_CACHE_AGED 2 #define NGX_HTTP_CACHE_THE_SAME 3 -int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx); -int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq); -int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx, - ngx_str_t *temp_file); - ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache, + ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t *crc); -ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *cache, + +ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *hash, + ngx_http_cache_t *cache, + ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t crc, - ngx_log_t *log); + ngx_str_t *value, ngx_log_t *log); +void ngx_http_cache_free(ngx_http_cache_t *cache, + ngx_str_t *key, ngx_str_t *value, ngx_log_t *log); void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash, ngx_http_cache_t *cache, ngx_log_t *log); +int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx); +int ngx_http_cache_open_file(ngx_http_cache_ctx_t *ctx, ngx_file_uniq_t uniq); +int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx, + ngx_str_t *temp_file); + +int ngx_http_send_cached(ngx_http_request_t *r); + int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, ngx_dir_t *dir); @@ -100,8 +118,4 @@ int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -extern ngx_module_t ngx_http_cache_module; - - - #endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */ diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 4018f4188..3046ca882 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -38,173 +38,180 @@ static ngx_conf_post_t ngx_http_lowat_post = { ngx_http_lowat_check } ; static ngx_command_t ngx_http_core_commands[] = { - {ngx_string("server"), - NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_server_block, - 0, - 0, - NULL}, - - {ngx_string("connection_pool_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, connection_pool_size), - NULL}, - - {ngx_string("post_accept_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, post_accept_timeout), - NULL}, - - {ngx_string("request_pool_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, request_pool_size), - NULL}, - - {ngx_string("client_header_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, client_header_timeout), - NULL}, - - {ngx_string("client_header_buffer_size"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size), - NULL}, - - {ngx_string("large_client_header"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_core_srv_conf_t, large_client_header), - NULL}, - - {ngx_string("location"), - NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12, - ngx_location_block, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL}, - - {ngx_string("listen"), + { ngx_string("server"), + NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_server_block, + 0, + 0, + NULL }, + + { ngx_string("connection_pool_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, connection_pool_size), + NULL }, + + { ngx_string("post_accept_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, post_accept_timeout), + NULL }, + + { ngx_string("request_pool_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, request_pool_size), + NULL }, + + { ngx_string("client_header_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, client_header_timeout), + NULL }, + + { ngx_string("client_header_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size), + NULL }, + + { ngx_string("large_client_header"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, large_client_header), + NULL }, + + { ngx_string("location"), + NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12, + ngx_location_block, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("listen"), #if 0 - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, #else - NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, #endif - ngx_set_listen, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL}, - - {ngx_string("server_name"), - NGX_HTTP_SRV_CONF|NGX_CONF_1MORE, - ngx_set_server_name, - NGX_HTTP_SRV_CONF_OFFSET, - 0, - NULL}, - - {ngx_string("types"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF - |NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_types_block, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, - - {ngx_string("default_type"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, default_type), - NULL}, - - {ngx_string("root"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, doc_root), - NULL}, - - {ngx_string("client_body_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, client_body_timeout), - NULL}, - - {ngx_string("sendfile"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, sendfile), - NULL}, - - {ngx_string("send_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, send_timeout), - NULL}, - - {ngx_string("send_lowat"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, send_lowat), - &ngx_http_lowat_post}, - - {ngx_string("keepalive_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, keepalive_timeout), - NULL}, - - {ngx_string("lingering_time"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, lingering_time), - NULL}, - - {ngx_string("lingering_timeout"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, lingering_timeout), - NULL}, - - {ngx_string("msie_padding"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_core_loc_conf_t, msie_padding), - NULL}, - - {ngx_string("error_page"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, - ngx_set_error_page, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, - - {ngx_string("error_log"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_set_error_log, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, - - ngx_null_command + ngx_set_listen, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("server_name"), + NGX_HTTP_SRV_CONF|NGX_CONF_1MORE, + ngx_set_server_name, + NGX_HTTP_SRV_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("types"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF + |NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_types_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("default_type"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, default_type), + NULL }, + + { ngx_string("root"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, doc_root), + NULL }, + + { ngx_string("client_body_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, client_body_timeout), + NULL }, + + { ngx_string("sendfile"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, sendfile), + NULL }, + + { ngx_string("send_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, send_timeout), + NULL }, + + { ngx_string("send_lowat"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, send_lowat), + &ngx_http_lowat_post }, + + { ngx_string("keepalive_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, keepalive_timeout), + NULL }, + + { ngx_string("lingering_time"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, lingering_time), + NULL }, + + { ngx_string("lingering_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, lingering_timeout), + NULL }, + + { ngx_string("msie_padding"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, msie_padding), + NULL }, + + { ngx_string("error_page"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, + ngx_set_error_page, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("error_log"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_set_error_log, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("open_file_cache"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE4, + ngx_http_set_cache_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, open_files), + NULL }, + + ngx_null_command }; @@ -301,16 +308,23 @@ static void ngx_http_phase_event_handler(ngx_event_t *ev) static void ngx_http_run_phases(ngx_http_request_t *r) { - int rc; + char *path; + ngx_int_t rc; ngx_http_handler_pt *h; + ngx_http_core_loc_conf_t *clcf; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - rc = NGX_DECLINED; - for (/* void */; r->phase < NGX_HTTP_LAST_PHASE; r->phase++) { + if (r->phase == NGX_HTTP_CONTENT_PHASE && r->content_handler) { + r->connection->write->event_handler = ngx_http_empty_handler; + rc = r->content_handler(r); + ngx_http_finalize_request(r, rc); + return; + } + h = cmcf->phases[r->phase].handlers.elts; for (r->phase_handler = cmcf->phases[r->phase].handlers.nelts - 1; r->phase_handler >= 0; @@ -319,6 +333,12 @@ static void ngx_http_run_phases(ngx_http_request_t *r) rc = h[r->phase_handler](r); if (rc == NGX_DONE) { + + /* + * we should never use r here because + * it could point to already freed data + */ + return; } @@ -330,38 +350,45 @@ static void ngx_http_run_phases(ngx_http_request_t *r) return; } - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_ERROR) { ngx_http_finalize_request(r, rc); return; } + if (rc == NGX_OK && r->phase == NGX_HTTP_CONTENT_PHASE) { + ngx_http_finalize_request(r, 0); + return; + } + if (rc == NGX_OK && cmcf->phases[r->phase].type == NGX_OK) { break; } } + } - if (cmcf->phases[r->phase].post_handler) { - rc = cmcf->phases[r->phase].post_handler(r); - if (rc == NGX_AGAIN) { - return; - } + if (r->uri.data[r->uri.len - 1] == '/') { - if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { - ngx_http_finalize_request(r, rc); - return; - } - } - } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (r->content_handler) { - r->connection->write->event_handler = ngx_http_empty_handler; - rc = r->content_handler(r); - ngx_http_finalize_request(r, rc); + if (!(path = ngx_palloc(r->pool, clcf->doc_root.len + r->uri.len))) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_cpystrn(ngx_cpymem(path, clcf->doc_root.data, clcf->doc_root.len), + r->uri.data, r->uri.len + 1); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "directory index of \"%s\" is forbidden", path); + + ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN); return; } - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found"); + + ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); return; } @@ -500,6 +527,55 @@ ngx_log_debug(r->connection->log, "trans: %s: %d" _ } +ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r) +{ + uint32_t key; + ngx_int_t i; + ngx_http_type_t *type; + ngx_http_core_loc_conf_t *clcf; + + if (!(r->headers_out.content_type = + ngx_http_add_header(&r->headers_out, ngx_http_headers_out))) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + r->headers_out.content_type->key.len = 0; + r->headers_out.content_type->key.data = NULL; + r->headers_out.content_type->value.len = 0; + r->headers_out.content_type->value.data = NULL; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (r->exten.len) { +#if 0 + key = ngx_crc(r->exten.data, r->exten.key); +#endif + ngx_http_types_hash_key(key, r->exten); + + type = clcf->types[key].elts; + for (i = 0; i < clcf->types[key].nelts; i++) { + if (r->exten.len != type[i].exten.len) { + continue; + } + + if (ngx_memcmp(r->exten.data, type[i].exten.data, r->exten.len) + == 0) + { + r->headers_out.content_type->value = type[i].type; + break; + } + } + } + + if (r->headers_out.content_type->value.len == 0) { + r->headers_out.content_type->value = clcf->default_type; + } + + return NGX_OK; +} + + int ngx_http_send_header(ngx_http_request_t *r) { if (r->main) { @@ -870,7 +946,7 @@ static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) int i, key; ngx_str_t *args; - ngx_http_type_t *t; + ngx_http_type_t *type; if (lcf->types == NULL) { ngx_test_null(lcf->types, @@ -889,11 +965,9 @@ static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) for (i = 1; i < cf->args->nelts; i++) { ngx_http_types_hash_key(key, args[i]); - ngx_test_null(t, ngx_push_array(&lcf->types[key]), NGX_CONF_ERROR); - t->exten.len = args[i].len; - t->exten.data = args[i].data; - t->type.len = args[0].len; - t->type.data = args[0].data; + ngx_test_null(type, ngx_push_array(&lcf->types[key]), NGX_CONF_ERROR); + type->exten = args[i]; + type->type = args[0]; } return NGX_CONF_OK; @@ -1124,6 +1198,10 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1); + if (conf->open_files == NULL) { + conf->open_files = prev->open_files; + } + return NGX_CONF_OK; } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 20f124c75..ed228d791 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -17,15 +17,19 @@ typedef struct { } ngx_http_listen_t; +typedef enum { + NGX_HTTP_REWRITE_PHASE = 0, + NGX_HTTP_FIND_CONFIG_PHASE, + NGX_HTTP_CONTENT_PHASE, + NGX_HTTP_LAST_PHASE +} ngx_http_phases; + + typedef struct { ngx_array_t handlers; int type; /* NGX_OK, NGX_DECLINED */ - ngx_http_handler_pt post_handler; } ngx_http_phase_t; -#define NGX_HTTP_REWRITE_PHASE 0 -#define NGX_HTTP_TRANSLATE_PHASE 1 -#define NGX_HTTP_LAST_PHASE 2 typedef struct { ngx_array_t servers; /* array of ngx_http_core_srv_conf_t */ @@ -128,36 +132,17 @@ typedef struct { int msie_padding; /* msie_padding */ ngx_array_t *error_pages; /* error_page */ + ngx_http_cache_hash_t *open_files; + ngx_regex_t *regex; unsigned exact_match:1; - unsigned auto_redirect:1; ngx_log_t *err_log; } ngx_http_core_loc_conf_t; - - -#if 0 -typedef struct { - int dummy; -} ngx_http_core_conf_t; -#endif - - -#if 0 -#define ngx_http_set_loc_handler(conf_ctx, ngx_http_handler) \ - { \ - ngx_http_conf_ctx_t *cx = conf_ctx; \ - ngx_http_core_loc_conf_t *lcf; \ - lcf = cx->loc_conf[ngx_http_core_module_ctx.index]; \ - lcf->handler = ngx_http_handler; \ - } -#endif - - extern ngx_http_module_t ngx_http_core_module_ctx; extern ngx_module_t ngx_http_core_module; @@ -168,6 +153,8 @@ extern int ngx_http_max_module; int ngx_http_find_location_config(ngx_http_request_t *r); int ngx_http_core_translate_handler(ngx_http_request_t *r); +ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r); + int ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args); int ngx_http_error(ngx_http_request_t *r, int error); diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 17706bb4d..dd97433ed 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -642,6 +642,7 @@ int ngx_http_parse_complex_uri(ngx_http_request_t *r) state = sw_usual; p = r->uri_start; u = r->uri.data; + r->uri_ext = NULL; ch = *p++; @@ -654,6 +655,7 @@ ngx_log_debug(r->connection->log, "S: %d UN: '%x:%c', URI: '%c'" _ case sw_usual: switch(ch) { case '/': + r->uri_ext = NULL; state = sw_slash; *u++ = ch; break; @@ -661,6 +663,8 @@ ngx_log_debug(r->connection->log, "S: %d UN: '%x:%c', URI: '%c'" _ quoted_state = state; state = sw_quoted; break; + case '.': + r->uri_ext = u + 1; default: *u++ = ch; break; @@ -811,5 +815,17 @@ ngx_log_debug(r->connection->log, "S: %d UN: '%x:%c', URI: '%c'" _ r->uri.len = u - r->uri.data; r->uri.data[r->uri.len] = '\0'; + if (r->uri_ext) { + r->exten.len = u - r->uri_ext; + + if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); + } + + r->uri_ext = NULL; + return NGX_OK; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 28308dc00..a8c2d6c75 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -359,6 +359,21 @@ static void ngx_http_process_request_line(ngx_event_t *rev) if (r->complex_uri) { rc = ngx_http_parse_complex_uri(r); + if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { + ngx_http_close_request(r, rc); + ngx_http_close_connection(c); + return; + } + + if (rc != NGX_OK) { + r->request_line.len = r->request_end - r->request_start; + r->request_line.data = r->request_start; + r->request_line.data[r->request_line.len] = '\0'; + + ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); + return; + } + } else { ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); } @@ -389,16 +404,6 @@ static void ngx_http_process_request_line(ngx_event_t *rev) } - if (rc != NGX_OK) { - /* - * we check ngx_http_parse_complex_uri() result here to log - * the request line - */ - ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); - return; - } - - if (r->uri_ext) { /* copy URI extention */ @@ -536,7 +541,8 @@ static void ngx_http_process_request_headers(ngx_event_t *rev) c = rev->data; r = c->data; - ngx_log_debug(rev->log, "http process request header line"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, + "http process request header line"); if (rev->timedout) { ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); @@ -1387,13 +1393,16 @@ int ngx_http_send_last(ngx_http_request_t *r) void ngx_http_close_request(ngx_http_request_t *r, int error) { ngx_int_t i; + ngx_log_t *log; ngx_http_log_ctx_t *ctx; ngx_http_cleanup_t *cleanup; - ngx_log_debug(r->connection->log, "close http request"); + log = r->connection->log; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request"); if (r->pool == NULL) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed"); return; } @@ -1406,29 +1415,36 @@ void ngx_http_close_request(ngx_http_request_t *r, int error) cleanup = r->cleanup.elts; for (i = 0; i < r->cleanup.nelts; i++) { + if (!cleanup[i].valid) { + continue; + } + if (cleanup[i].cache) { ngx_http_cache_unlock(cleanup[i].data.cache.hash, - cleanup[i].data.cache.cache, - r->connection->log); + cleanup[i].data.cache.cache, log); continue; } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d", + cleanup[i].data.file.fd); + if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", cleanup[i].data.file.name); } } + /* STUB */ if (r->file.fd != NGX_INVALID_FILE) { if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", r->file.name.data); } } /* ctx->url was allocated from r->pool */ - ctx = r->connection->log->data; + ctx = log->data; ctx->url = NULL; ngx_destroy_pool(r->pool); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 08afcd53e..82e8bf79b 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -144,7 +144,7 @@ typedef struct { } ngx_http_headers_out_t; -typedef struct { +struct ngx_http_cleanup_s { union { struct { ngx_fd_t fd; @@ -157,8 +157,9 @@ typedef struct { } cache; } data; + unsigned valid:1; unsigned cache:1; -} ngx_http_cleanup_t; +}; typedef int (*ngx_http_handler_pt)(ngx_http_request_t *r); @@ -194,8 +195,6 @@ struct ngx_http_request_s { ngx_str_t args; ngx_str_t exten; ngx_str_t unparsed_uri; - ngx_str_t path; - int path_allocated; ngx_http_request_t *main; diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index bb89336fe..e76f4c6f4 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -5,16 +5,16 @@ /* - * sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 and 1176 - * or in 6 packets: 5x1460 and 892. Besides although sendfile() allows - * to pass the header and the trailer it never sends the header or the trailer - * with the part of the file in one packet. So we use TCP_NOPUSH (similar - * to Linux's TCP_CORK) to postpone the sending - it not only sends the header - * and the first part of the file in one packet but also sends 4K pages - * in the full packets. + * FreeBSD's sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460 + * and 1176 or in 6 packets: 5x1460 and 892. Besides although sendfile() + * allows to pass the header and the trailer it never sends the header or + * the trailer with the part of the file in one packet. So we use TCP_NOPUSH + * (similar to Linux's TCP_CORK) to postpone the sending - it not only sends + * the header and the first part of the file in one packet but also sends + * 4K pages in the full packets. * - * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush the pending - * data that less than MSS so the data can be sent with 5 second delay. + * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending + * data that less than MSS so that data can be sent with 5 second delay. * We do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used * for non-keepalive HTTP connections. */ diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index d96d93df7..d4e45bbe4 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -6,10 +6,9 @@ /* * On Linux up to 2.4.21 sendfile() (syscall #187) works with 32-bit - * offsets only and the including <sys/sendfile.h> breaks building - * if off_t is 64 bit wide. So we use own sendfile() definition where - * offset paramter is int32_t. It allows to use sendfile() with - * the file parts below 2G. + * offsets only and the including <sys/sendfile.h> breaks building if + * off_t is 64 bit wide. So we use own sendfile() definition where offset + * parameter is int32_t and use sendfile() with the file parts below 2G. * * Linux 2.4.21 has a new sendfile64() syscall #239. */ |