diff --git a/auto/lib/make b/auto/lib/make index 7acae504f..2c2d23286 100644 --- a/auto/lib/make +++ b/auto/lib/make @@ -1,12 +1,12 @@ -if [ $PCRE != NONE -a $PCRE != NO ]; then +if [ $PCRE != NONE -a $PCRE != NO -a $PCRE != YES ]; then . auto/lib/pcre/make fi -if [ $MD5 != NONE -a $MD5 != NO ]; then +if [ $MD5 != NONE -a $MD5 != NO -a $MD5 != YES ]; then . auto/lib/md5/make fi -if [ $ZLIB != NONE -a $ZLIB != NO ]; then +if [ $ZLIB != NONE -a $ZLIB != NO -a $ZLIB != YES ]; then . auto/lib/zlib/make fi diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf index 8871038b0..3fc1af608 100644 --- a/auto/lib/md5/conf +++ b/auto/lib/md5/conf @@ -41,16 +41,17 @@ if [ $MD5 != NONE ]; then else if [ $PLATFORM != win32 ]; then - MD5=NO + MD5=NO + ngx_lib_cflags= - # Solaris 8/9 + # Solaris 8/9 - ngx_lib_inc="#include + ngx_lib_inc="#include #include " - ngx_lib="rsaref md5 library" - ngx_lib_test="MD5_CTX md5; MD5Init(&md5)" - ngx_libs=-lmd5 - . auto/lib/test + ngx_lib="rsaref md5 library" + ngx_lib_test="MD5_CTX md5; MD5Init(&md5)" + ngx_libs=-lmd5 + . auto/lib/test if [ $ngx_found = yes ]; then @@ -64,7 +65,7 @@ else ngx_lib="rsaref md library" ngx_lib_test="MD5_CTX md5; MD5Init(&md5)" - ngx_libs=-lmd + #ngx_libs=-lmd . auto/lib/test fi @@ -76,13 +77,16 @@ else ngx_found=no else - # OpenSSL crypto library + if [ $MD5 = NO ]; then - ngx_inc="#include " - ngx_lib="OpenSSL md5 crypto library" - ngx_lib_test="MD5_CTX md5; MD5_Init(&md5)" - ngx_libs=-lcrypto - . auto/lib/test + # OpenSSL crypto library + + ngx_lib_inc="#include " + ngx_lib="OpenSSL md5 crypto library" + ngx_lib_test="MD5_CTX md5; MD5_Init(&md5)" + ngx_libs=-lcrypto + . auto/lib/test + fi fi diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf index a2ab1c6b5..29c561b81 100644 --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -41,6 +41,9 @@ else if [ $PLATFORM != win32 ]; then PCRE=NO + ngx_lib_cflags= + + # Linux ngx_lib_inc="#include " ngx_lib="PCRE library" @@ -55,6 +58,7 @@ else CORE_SRCS="$CORE_SRCS $REGEX_SRCS" CORE_LIBS="$CORE_LIBS $ngx_libs" PCRE=YES + ngx_found=no else # FreeBSD PCRE port. diff --git a/auto/lib/zlib/conf b/auto/lib/zlib/conf index 9c2178fad..37c1fa7ef 100644 --- a/auto/lib/zlib/conf +++ b/auto/lib/zlib/conf @@ -35,8 +35,11 @@ if [ $ZLIB != NONE ]; then else if [ $PLATFORM != win32 ]; then - ngx_lib_inc="#include " + # FreeBSD, Solaris, Linux + + ngx_lib_cflags= + ngx_lib_inc="#include " ngx_lib="zlib library" ngx_lib_test="z_stream z; deflate(&z, Z_NO_FLUSH)" ngx_libs=-lz diff --git a/auto/lib/zlib/make b/auto/lib/zlib/make index 240b6474b..d25642533 100644 --- a/auto/lib/zlib/make +++ b/auto/lib/zlib/make @@ -77,8 +77,11 @@ case $PLATFORM in done=YES ;; + NO) + ;; + *) - echo "$0: error: invalid --with-zlib=asm=$ZLIB_ASM option." + echo "$0: error: invalid --with-zlib-asm=$ZLIB_ASM option." echo "The valid values are \"pentium\" and \"pentiumpro\" only". echo diff --git a/auto/os/conf b/auto/os/conf index 31a041f96..94fdbcd56 100644 --- a/auto/os/conf +++ b/auto/os/conf @@ -30,11 +30,16 @@ case $PLATFORM in win32) CORE_INCS="$WIN32_INCS" CORE_DEPS="$WIN32_DEPS" - CORE_SRCS="$WIN32_SRCS $SELECT_SRCS $IOCP_SRCS" + CORE_SRCS="$WIN32_SRCS $IOCP_SRCS" OS_CONFIG="$WIN32_CONFIG" - EVENT_MODULES="$EVENT_MODULES $SELECT_MODULE $IOCP_MODULE" + EVENT_MODULES="$EVENT_MODULES $IOCP_MODULE" EVENT_FOUND=YES + if [ $EVENT_SELECT = NO ]; then + CORE_SRCS="$CORE_SRCS $SELECT_SRCS" + EVENT_MODULES="$EVENT_MODULES $SELECT_MODULE" + fi + have=HAVE_AIO . auto/have have=HAVE_IOCP . auto/have CORE_LIBS="$CORE_LIBS ws2_32.lib" diff --git a/src/core/nginx.c b/src/core/nginx.c index 766257c8a..3c5f789fe 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -140,11 +140,19 @@ int main(int argc, char *const *argv) cycle = ngx_init_cycle(&init_cycle); if (cycle == NULL) { + if (ngx_test_config) { + ngx_log_error(NGX_LOG_EMERG, log, 0, + "the configuration file %s test failed", + init_cycle.conf_file.data); + } + return 1; } if (ngx_test_config) { - ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "config syntax is ok"); + ngx_log_error(NGX_LOG_INFO, log, 0, + "the configuration file %s was tested successfully", + init_cycle.conf_file.data); return 0; } diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 94414ae12..bde3171ae 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -138,6 +138,12 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) return NULL; } + if (ngx_test_config) { + ngx_log_error(NGX_LOG_INFO, log, 0, + "the configuration file %s syntax is ok", + cycle->conf_file.data); + } + for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { @@ -274,10 +280,12 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) #if !(WIN32) - if (dup2(cycle->log->file->fd, STDERR_FILENO) == NGX_ERROR) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "dup2(STDERR) failed"); - failed = 1; + if (!failed && !ngx_test_config) { + if (dup2(cycle->log->file->fd, STDERR_FILENO) == NGX_ERROR) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "dup2(STDERR) failed"); + failed = 1; + } } #endif @@ -299,6 +307,11 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) } } + if (ngx_test_config) { + ngx_destroy_pool(pool); + return NULL; + } + ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].new && ls[i].fd == -1) { diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index 285bd8340..94e410495 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -20,7 +20,7 @@ int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) ngx_chain_t *cl, *out, **last_out; /* - * the short path for the case when the chain ctx->in is empty + * the short path for the case when the ctx->in chain is empty * and the incoming chain is empty too or it has the single hunk * that does not require the copy */ @@ -54,9 +54,14 @@ int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) while (ctx->in) { + /* + * cycle while there are the ctx->in hunks + * or there are the free output hunks to copy in + */ + if (!ngx_output_chain_need_to_copy(ctx, ctx->in->hunk)) { - /* move the chain link to the chain out */ + /* move the chain link to the output chain */ cl = ctx->in; ctx->in = cl->next; @@ -133,7 +138,7 @@ int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) return rc; } - /* delete the completed hunk from the chain ctx->in */ + /* delete the completed hunk from the ctx->in chain */ if (ngx_hunk_size(ctx->in->hunk) == 0) { ctx->in = ctx->in->next; @@ -157,6 +162,10 @@ int ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) ngx_chain_update_chains(&ctx->free, &ctx->busy, &out, ctx->tag); last_out = &out; + + if (last == NGX_ERROR) { + return last; + } } } diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c index 8c22ac629..cf3910c56 100644 --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -18,15 +18,19 @@ typedef struct { int level; size_t wbits; size_t memlevel; + size_t min_length; } ngx_http_gzip_conf_t; -enum { - NGX_HTTP_GZIP_PROXIED_OFF = 0, - NGX_HTTP_GZIP_PROXIED_NOCACHABLE, - NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE, - NGX_HTTP_GZIP_PROXIED_ON -}; +#define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 +#define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 +#define NGX_HTTP_GZIP_PROXIED_NO_CACHE 0x0008 +#define NGX_HTTP_GZIP_PROXIED_NO_STORE 0x0010 +#define NGX_HTTP_GZIP_PROXIED_PRIVATE 0x0020 +#define NGX_HTTP_GZIP_PROXIED_NO_LM 0x0040 +#define NGX_HTTP_GZIP_PROXIED_NO_ETAG 0x0080 +#define NGX_HTTP_GZIP_PROXIED_AUTH 0x0100 +#define NGX_HTTP_GZIP_PROXIED_ANY 0x0200 typedef struct { @@ -37,7 +41,7 @@ typedef struct { ngx_chain_t **last_out; ngx_hunk_t *in_hunk; ngx_hunk_t *out_hunk; - int hunks; + ngx_int_t hunks; off_t length; @@ -58,10 +62,11 @@ typedef struct { } ngx_http_gzip_ctx_t; +static int ngx_http_gzip_proxied(ngx_http_request_t *r, + ngx_http_gzip_conf_t *conf); static void *ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size); static void ngx_http_gzip_filter_free(void *opaque, void *address); - ngx_inline static int ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx); static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf, @@ -94,11 +99,16 @@ static ngx_conf_enum_t ngx_http_gzip_http_version[] = { }; -static ngx_conf_enum_t ngx_http_gzip_proxied[] = { +static ngx_conf_bitmask_t ngx_http_gzip_proxied_mask[] = { { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF }, - { ngx_string("nocachable"), NGX_HTTP_GZIP_PROXIED_NOCACHABLE }, - { ngx_string("poor_cachable"), NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE }, - { ngx_string("on"), NGX_HTTP_GZIP_PROXIED_ON }, + { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED }, + { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE }, + { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE }, + { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE }, + { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM }, + { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG }, + { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH }, + { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY }, { ngx_null_string, 0 } }; @@ -156,10 +166,17 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = { { ngx_string("gzip_proxied"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, - ngx_conf_set_enum_slot, + ngx_conf_set_bitmask_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_gzip_conf_t, proxied), - &ngx_http_gzip_proxied }, + &ngx_http_gzip_proxied_mask }, + + { ngx_string("gzip_min_length"), + 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_gzip_conf_t, min_length), + NULL}, ngx_null_command }; @@ -221,7 +238,6 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static int ngx_http_gzip_header_filter(ngx_http_request_t *r) { - time_t date, expires; ngx_http_gzip_ctx_t *ctx; ngx_http_gzip_conf_t *conf; @@ -234,6 +250,8 @@ static int ngx_http_gzip_header_filter(ngx_http_request_t *r) || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || r->headers_in.accept_encoding == NULL + || (r->headers_out.content_length_n != -1 + && r->headers_out.content_length_n < conf->min_length) || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL ) { @@ -249,66 +267,15 @@ static int ngx_http_gzip_header_filter(ngx_http_request_t *r) } - if (r->headers_in.via && conf->proxied != NGX_HTTP_GZIP_PROXIED_ON) { - - if (conf->proxied == NGX_HTTP_GZIP_PROXIED_OFF) { + if (r->headers_in.via) { + if (conf->proxied & NGX_HTTP_GZIP_PROXIED_OFF) { return ngx_http_next_header_filter(r); } - if (r->headers_out.expires) { - expires = ngx_http_parse_time(r->headers_out.expires->value.data, - r->headers_out.expires->value.len); - if (expires == NGX_ERROR) { - return ngx_http_next_header_filter(r); - } - - if (r->headers_out.date) { - date = ngx_http_parse_time(r->headers_out.date->value.data, - r->headers_out.date->value.len); - if (date == NGX_ERROR) { - return ngx_http_next_header_filter(r); - } - - } else { - date = ngx_cached_time; - } - - if (expires >= date) { - return ngx_http_next_header_filter(r); - } - - } else if (r->headers_out.cache_control) { - - if (conf->proxied == NGX_HTTP_GZIP_PROXIED_NOCACHABLE) { - if (ngx_strstr(r->headers_out.cache_control->value.data, - "no-cache") == NULL) - { - return ngx_http_next_header_filter(r); - } - - } else { /* NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE */ - - /* STUB: should be one cycle for all values */ - - if (ngx_strstr(r->headers_out.cache_control->value.data, - "no-cache") == NULL - && ngx_strstr(r->headers_out.cache_control->value.data, - "private") == NULL - && ngx_strstr(r->headers_out.cache_control->value.data, - "no-store") == NULL) - { - return ngx_http_next_header_filter(r); - } - } - - } else if (conf->proxied == NGX_HTTP_GZIP_PROXIED_NOCACHABLE) { + if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_ANY) + && ngx_http_gzip_proxied(r, conf) == NGX_DECLINED) + { return ngx_http_next_header_filter(r); - - } else { /* NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE */ - - if (r->headers_out.last_modified || r->headers_out.etag) { - return ngx_http_next_header_filter(r); - } } } @@ -354,6 +321,89 @@ static int ngx_http_gzip_header_filter(ngx_http_request_t *r) } +static int ngx_http_gzip_proxied(ngx_http_request_t *r, + ngx_http_gzip_conf_t *conf) +{ + time_t date, expires; + + if (r->headers_in.authorization + && (conf->proxied & NGX_HTTP_GZIP_PROXIED_AUTH)) + { + return NGX_OK; + } + + if (r->headers_out.expires) { + + if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_EXPIRED)) { + return NGX_DECLINED; + } + + expires = ngx_http_parse_time(r->headers_out.expires->value.data, + r->headers_out.expires->value.len); + if (expires == NGX_ERROR) { + return NGX_DECLINED; + } + + if (r->headers_out.date) { + date = ngx_http_parse_time(r->headers_out.date->value.data, + r->headers_out.date->value.len); + if (date == NGX_ERROR) { + return NGX_DECLINED; + } + + } else { + date = ngx_cached_time; + } + + if (expires < date) { + return NGX_OK; + } + + return NGX_DECLINED; + } + + if (r->headers_out.cache_control) { + + if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_CACHE) + && ngx_strstr(r->headers_out.cache_control->value.data, "no-cache") + == NULL) + { + return NGX_OK; + } + + if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_STORE) + && ngx_strstr(r->headers_out.cache_control->value.data, "no-store") + == NULL) + { + return NGX_OK; + } + + if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_PRIVATE) + && ngx_strstr(r->headers_out.cache_control->value.data, "private") + == NULL) + { + return NGX_OK; + } + + return NGX_DECLINED; + } + + if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_LM) + && r->headers_out.last_modified) + { + return NGX_DECLINED; + } + + if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_ETAG) + && r->headers_out.etag) + { + return NGX_DECLINED; + } + + return NGX_OK; +} + + static int ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { int rc, wbits, memlevel, last; @@ -770,17 +820,24 @@ static void *ngx_http_gzip_create_conf(ngx_conf_t *cf) ngx_pcalloc(cf->pool, sizeof(ngx_http_gzip_conf_t)), NGX_CONF_ERROR); + /* set by ngx_pcalloc(): + + conf->bufs.num = 0; + conf->proxied = 0; + + */ + + conf->enable = NGX_CONF_UNSET; conf->no_buffer = NGX_CONF_UNSET; - /* conf->bufs.num = 0; */ conf->http_version = NGX_CONF_UNSET_UINT; - conf->proxied = NGX_CONF_UNSET_UINT; conf->level = NGX_CONF_UNSET; - conf->wbits = NGX_CONF_UNSET; - conf->memlevel = NGX_CONF_UNSET; + conf->wbits = NGX_CONF_UNSET_UINT; + conf->memlevel = NGX_CONF_UNSET_UINT; + conf->min_length = NGX_CONF_UNSET_UINT; return conf; } @@ -799,13 +856,15 @@ static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version, NGX_HTTP_VERSION_11); - ngx_conf_merge_unsigned_value(conf->proxied, prev->proxied, - NGX_HTTP_GZIP_PROXIED_OFF); + ngx_conf_merge_bitmask_value(conf->proxied, prev->proxied, + (NGX_CONF_BITMASK_SET + |NGX_HTTP_GZIP_PROXIED_OFF)); ngx_conf_merge_value(conf->level, prev->level, 1); ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS); ngx_conf_merge_size_value(conf->memlevel, prev->memlevel, MAX_MEM_LEVEL - 1); + ngx_conf_merge_size_value(conf->min_length, prev->min_length, 0); ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); return NGX_CONF_OK;