diff options
author | Igor Sysoev <igor@sysoev.ru> | 2004-10-11 19:07:03 +0400 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2004-10-11 19:07:03 +0400 |
commit | 924bd79e317e9a137c0d1b9d349185758a628ec4 (patch) | |
tree | f877c8b19e53e7d0a7683e3dd9aeb713146c4a8f /src/http | |
parent | aef13d7f6660f4f8d2c50c95b8e182e62c115f88 (diff) |
nginx-0.1.1-RELEASE importrelease-0.1.1
*) Feature: the gzip_types directive.
*) Feature: the tcp_nodelay directive.
*) Feature: the send_lowat directive is working not only on OSes that
support kqueue NOTE_LOWAT, but also on OSes that support SO_SNDLOWAT.
*) Feature: the setproctitle() emulation for Linux and Solaris.
*) Bugfix: the "Location" header rewrite bug fixed while the proxying.
*) Bugfix: the ngx_http_chunked_module module may get caught in an
endless loop.
*) Bugfix: the /dev/poll module bugs fixed.
*) Bugfix: the responses were corrupted when the temporary files were
used while the proxying.
*) Bugfix: the unescaped requests were passed to the backend.
*) Bugfix: while the build configuration on Linux 2.4 the
--with-poll_module parameter was required.
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_chunked_filter.c | 10 | ||||
-rw-r--r-- | src/http/modules/ngx_http_gzip_filter.c | 179 | ||||
-rw-r--r-- | src/http/modules/ngx_http_userid_filter.c | 4 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.c | 99 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_handler.h | 1 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_header.c | 20 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_parse.c | 3 | ||||
-rw-r--r-- | src/http/modules/proxy/ngx_http_proxy_upstream.c | 33 | ||||
-rw-r--r-- | src/http/ngx_http_copy_filter.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 23 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.h | 1 | ||||
-rw-r--r-- | src/http/ngx_http_header_filter.c | 1 | ||||
-rw-r--r-- | src/http/ngx_http_parse.c | 9 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 48 | ||||
-rw-r--r-- | src/http/ngx_http_request.h | 7 |
15 files changed, 306 insertions, 134 deletions
diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c index a71839a29..211246149 100644 --- a/src/http/modules/ngx_http_chunked_filter.c +++ b/src/http/modules/ngx_http_chunked_filter.c @@ -83,10 +83,12 @@ static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r, size += ngx_buf_size(cl->buf); - ngx_test_null(tl, ngx_alloc_chain_link(r->pool), NGX_ERROR); - tl->buf = cl->buf; - *ll = tl; - ll = &tl->next; + if (cl->buf->flush || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) { + ngx_test_null(tl, ngx_alloc_chain_link(r->pool), NGX_ERROR); + tl->buf = cl->buf; + *ll = tl; + ll = &tl->next; + } if (cl->next == NULL) { break; diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c index 72ccb0a0f..4089ffbdc 100644 --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -15,6 +15,8 @@ typedef struct { ngx_flag_t enable; ngx_flag_t no_buffer; + ngx_array_t *types; /* array of ngx_http_gzip_type_t */ + ngx_bufs_t bufs; ngx_uint_t http_version; @@ -27,6 +29,12 @@ typedef struct { } ngx_http_gzip_conf_t; +typedef struct { + ngx_str_t name; + ngx_uint_t enable; +} ngx_http_gzip_type_t; + + #define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 #define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 #define NGX_HTTP_GZIP_PROXIED_NO_CACHE 0x0008 @@ -57,10 +65,6 @@ typedef struct { unsigned flush:4; unsigned redo:1; unsigned done:1; -#if 0 - unsigned pass:1; - unsigned blocked:1; -#endif size_t zin; size_t zout; @@ -86,6 +90,8 @@ static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle); static void *ngx_http_gzip_create_conf(ngx_conf_t *cf); static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data); @@ -138,6 +144,13 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = { offsetof(ngx_http_gzip_conf_t, bufs), NULL }, + { ngx_string("gzip_types"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_gzip_set_types, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + { ngx_string("gzip_comp_level"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -211,7 +224,7 @@ ngx_module_t ngx_http_gzip_filter_module = { ngx_http_gzip_filter_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ ngx_http_gzip_filter_init, /* init module */ - NULL /* init child */ + NULL /* init process */ }; @@ -247,15 +260,20 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) { + ngx_uint_t i, found; ngx_http_gzip_ctx_t *ctx; ngx_http_gzip_conf_t *conf; + ngx_http_gzip_type_t *type; conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); if (!conf->enable - || r->headers_out.status != NGX_HTTP_OK + || (r->headers_out.status != NGX_HTTP_OK + && r->headers_out.status != NGX_HTTP_FORBIDDEN + && r->headers_out.status != NGX_HTTP_NOT_FOUND) || r->header_only || r->http_version < conf->http_version + || r->headers_out.content_type == NULL || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || r->headers_in.accept_encoding == NULL @@ -267,11 +285,21 @@ static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) return ngx_http_next_header_filter(r); } - /* TODO: "text/html" -> custom types */ - if (r->headers_out.content_type - && ngx_strncasecmp(r->headers_out.content_type->value.data, - "text/html", 9) != 0) - { + + found = 0; + type = conf->types->elts; + + for (i = 0; i < conf->types->nelts; i++) { + if (r->headers_out.content_type->value.len >= type[i].name.len + && ngx_strncasecmp(r->headers_out.content_type->value.data, + type[i].name.data, type[i].name.len) == 0) + { + found = 1; + break; + } + } + + if (!found) { return ngx_http_next_header_filter(r); } @@ -572,15 +600,9 @@ static ngx_int_t ngx_http_gzip_body_filter(ngx_http_request_t *r, ctx->bufs++; } else { -#if 0 - ctx->blocked = 1; -#endif break; } -#if 0 - ctx->blocked = 0; -#endif ctx->zstream.next_out = ctx->out_buf->pos; ctx->zstream.avail_out = conf->bufs.size; } @@ -646,10 +668,6 @@ static ngx_int_t ngx_http_gzip_body_filter(ngx_http_request_t *r, *ctx->last_out = cl; ctx->last_out = &cl->next; -#if 0 - ctx->pass = 1; -#endif - break; } @@ -712,9 +730,6 @@ static ngx_int_t ngx_http_gzip_body_filter(ngx_http_request_t *r, ctx->zstream.avail_out = 0; ctx->done = 1; -#if 0 - ctx->pass = 1; -#endif break; } @@ -725,47 +740,10 @@ static ngx_int_t ngx_http_gzip_body_filter(ngx_http_request_t *r, *ctx->last_out = cl; ctx->last_out = &cl->next; -#if 0 - ctx->pass = 1; -#endif - break; } } -#if 0 - - /* OLD CODE */ - - if (ctx->out) { - if (ctx->pass) { - ctx->pass = 0; - - } else if (last == NGX_AGAIN) { - return last; - } - - } else if (ctx->busy->buf && ngx_buf_size(ctx->busy->buf)) { - if (last != NGX_NONE) { - return last; - } - - } else if (ctx->blocked) { - if (last != NGX_NONE) { - return last; - } - - } else { - if (last == NGX_NONE) { - return NGX_OK; - } - - return last; - } -#endif - - /* NEW CODE */ - if (last == NGX_AGAIN) { return NGX_AGAIN; } @@ -774,8 +752,6 @@ static ngx_int_t ngx_http_gzip_body_filter(ngx_http_request_t *r, return NGX_OK; } - /**/ - last = ngx_http_next_body_filter(r, ctx->out); /* @@ -866,7 +842,7 @@ static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf, (float) ctx->zin / ctx->zout); #endif - /* we prefer do not use FPU */ + /* we prefer do not use the FPU */ zint = (ngx_uint_t) (ctx->zin / ctx->zout); zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100); @@ -947,6 +923,8 @@ static void *ngx_http_gzip_create_conf(ngx_conf_t *cf) conf->bufs.num = 0; conf->proxied = 0; + conf->types = NULL; + */ conf->enable = NGX_CONF_UNSET; @@ -969,6 +947,8 @@ static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, ngx_http_gzip_conf_t *prev = parent; ngx_http_gzip_conf_t *conf = child; + ngx_http_gzip_type_t *type; + ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize); @@ -986,6 +966,77 @@ static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, ngx_conf_merge_value(conf->min_length, prev->min_length, 0); ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); + if (conf->types == NULL) { + if (prev->types == NULL) { + conf->types = ngx_array_create(cf->pool, 1, + sizeof(ngx_http_gzip_type_t)); + if (conf->types == NULL) { + return NGX_CONF_ERROR; + } + + if (!(type = ngx_array_push(conf->types))) { + return NGX_CONF_ERROR; + } + + type->name.len = sizeof("text/html") - 1; + type->name.data = (u_char *) "text/html"; + type->enable = 1; + + } else { + conf->types = prev->types; + } + } + + return NGX_CONF_OK; +} + + +static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_gzip_conf_t *gcf = conf; + + ngx_str_t *value; + ngx_uint_t i; + ngx_http_gzip_type_t *type; + + if (gcf->types == NULL) { + gcf->types = ngx_array_create(cf->pool, 5, + sizeof(ngx_http_gzip_type_t)); + if (gcf->types == NULL) { + return NGX_CONF_ERROR; + } + + if (!(type = ngx_array_push(gcf->types))) { + return NGX_CONF_ERROR; + } + + type->name.len = sizeof("text/html") - 1; + type->name.data = (u_char *) "text/html"; + type->enable = 1; + } + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + + if (ngx_strcmp(value[i].data, "text/html") == 0) { + continue; + } + + if (!(type = ngx_array_push(gcf->types))) { + return NGX_CONF_ERROR; + } + + type->name.len = value[i].len; + + if (!(type->name.data = ngx_palloc(cf->pool, type->name.len + 1))) { + return NGX_CONF_ERROR; + } + + ngx_cpystrn(type->name.data, value[i].data, type->name.len + 1); + } + return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_userid_filter.c b/src/http/modules/ngx_http_userid_filter.c index 6cbad26c7..5f8e452ac 100644 --- a/src/http/modules/ngx_http_userid_filter.c +++ b/src/http/modules/ngx_http_userid_filter.c @@ -257,7 +257,7 @@ static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, src.data = start; dst.data = (u_char *) ctx->uid_got; - if (ngx_decode_base64(&src, &dst) == NGX_ERROR) { + if (ngx_decode_base64(&dst, &src) == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid userid cookie \"%s\"", cookies[i]->value.data); @@ -358,7 +358,7 @@ static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, src.data = (u_char *) ctx->uid_set; dst.data = p; - ngx_encode_base64(&src, &dst); + ngx_encode_base64(&dst, &src); p += dst.len; diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index 3fa2e0bf3..f0794f36e 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -29,6 +29,11 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, ngx_http_proxy_upstream_conf_t *u); +static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); + +static ngx_conf_post_t ngx_http_proxy_lowat_post = + { ngx_http_proxy_lowat_check } ; + static ngx_conf_bitmask_t next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR }, @@ -79,6 +84,13 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, send_timeout), NULL }, + { ngx_string("proxy_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_proxy_loc_conf_t, send_lowat), + &ngx_http_proxy_lowat_post }, + { ngx_string("proxy_preserve_host"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -877,6 +889,7 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) conf->connect_timeout = NGX_CONF_UNSET_MSEC; conf->send_timeout = NGX_CONF_UNSET_MSEC; + conf->send_lowat = NGX_CONF_UNSET_SIZE; conf->preserve_host = NGX_CONF_UNSET; conf->set_x_real_ip = NGX_CONF_UNSET; @@ -920,6 +933,7 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, ngx_conf_merge_msec_value(conf->connect_timeout, prev->connect_timeout, 60000); ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000); + ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0); ngx_conf_merge_value(conf->preserve_host, prev->preserve_host, 0); ngx_conf_merge_value(conf->set_x_real_ip, prev->set_x_real_ip, 0); @@ -1073,17 +1087,21 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, value = cf->args->elts; if (ngx_strncasecmp(value[1].data, "http://", 7) != 0) { - return "invalid URL prefix"; + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix"); + return NGX_CONF_ERROR; } - ngx_test_null(lcf->upstream, - ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_conf_t)), - NGX_CONF_ERROR); + lcf->upstream = ngx_pcalloc(cf->pool, + sizeof(ngx_http_proxy_upstream_conf_t)); + if (lcf->upstream == NULL) { + return NGX_CONF_ERROR; + } lcf->upstream->url.len = value[1].len; if (!(lcf->upstream->url.data = ngx_palloc(cf->pool, value[1].len + 1))) { return NGX_CONF_ERROR; } + ngx_cpystrn(lcf->upstream->url.data, value[1].data, value[1].len + 1); value[1].data += 7; @@ -1092,11 +1110,14 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream); if (err) { - return err; + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, err); + return NGX_CONF_ERROR; + } + + if (!(host = ngx_palloc(cf->pool, lcf->upstream->host.len + 1))) { + return NGX_CONF_ERROR; } - ngx_test_null(host, ngx_palloc(cf->pool, lcf->upstream->host.len + 1), - NGX_CONF_ERROR); ngx_cpystrn(host, lcf->upstream->host.data, lcf->upstream->host.len + 1); /* AF_INET only */ @@ -1115,11 +1136,12 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, /* MP: ngx_shared_palloc() */ - ngx_test_null(lcf->peers, - ngx_pcalloc(cf->pool, - sizeof(ngx_peers_t) - + sizeof(ngx_peer_t) * (i - 1)), - NGX_CONF_ERROR); + lcf->peers = ngx_pcalloc(cf->pool, + sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1)); + + if (lcf->peers == NULL) { + return NGX_CONF_ERROR; + } lcf->peers->number = i; @@ -1130,9 +1152,12 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, lcf->peers->peers[i].port = lcf->upstream->port; len = INET_ADDRSTRLEN + lcf->upstream->port_text.len + 1; - ngx_test_null(lcf->peers->peers[i].addr_port_text.data, - ngx_palloc(cf->pool, len), - NGX_CONF_ERROR); + + lcf->peers->peers[i].addr_port_text.data = + ngx_palloc(cf->pool, len); + if (lcf->peers->peers[i].addr_port_text.data == NULL) { + return NGX_CONF_ERROR; + } len = ngx_inet_ntop(AF_INET, &lcf->peers->peers[i].addr, @@ -1153,8 +1178,9 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, /* MP: ngx_shared_palloc() */ - ngx_test_null(lcf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)), - NGX_CONF_ERROR); + if (!(lcf->peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)))) { + return NGX_CONF_ERROR; + } lcf->peers->number = 1; @@ -1165,9 +1191,11 @@ static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, len = lcf->upstream->host.len + lcf->upstream->port_text.len + 1; - ngx_test_null(lcf->peers->peers[0].addr_port_text.data, - ngx_palloc(cf->pool, len + 1), - NGX_CONF_ERROR); + lcf->peers->peers[0].addr_port_text.data = + ngx_palloc(cf->pool, len + 1); + if (lcf->peers->peers[0].addr_port_text.data == NULL) { + return NGX_CONF_ERROR; + } len = lcf->upstream->host.len; @@ -1278,3 +1306,34 @@ static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, return "invalid port in upstream URL"; } + + +static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data) +{ +#if __FreeBSD__ + + ssize_t *np = data; + + if (*np >= ngx_freebsd_net_inet_tcp_sendspace) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_send_lowat\" must be less than %d " + "(sysctl net.inet.tcp.sendspace)", + ngx_freebsd_net_inet_tcp_sendspace); + + return NGX_CONF_ERROR; + } + + +#else + +#if 0 + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "\"proxy_send_lowat\" is not supported, ignored"); + + *np = 0; +#endif + +#endif + + return NGX_CONF_OK; +} diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h index 4dcc65387..728259c45 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -54,6 +54,7 @@ typedef struct { typedef struct { + size_t send_lowat; size_t header_buffer_size; size_t busy_buffers_size; size_t max_temp_file_size; diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c index 038001240..07722fc89 100644 --- a/src/http/modules/proxy/ngx_http_proxy_header.c +++ b/src/http/modules/proxy/ngx_http_proxy_header.c @@ -164,24 +164,26 @@ static int ngx_http_proxy_rewrite_location_header(ngx_http_proxy_ctx_t *p, return NGX_ERROR; } - /* - * we do not set r->headers_out.location to avoid the handling - * the local redirects without a host name by ngx_http_header_filter() - */ - -#if 0 - r->headers_out.location = location; -#endif - if (uc->url.len > loc->value.len || ngx_rstrncmp(loc->value.data, uc->url.data, uc->url.len) != 0) { + + /* + * we do not set r->headers_out.location here to avoid the handling + * the local redirects without a host name by ngx_http_header_filter() + */ + *location = *loc; return NGX_OK; } /* TODO: proxy_reverse */ + r->headers_out.location = location; + + location->key.len = 0; + location->key.data = NULL; + location->value.len = uc->location->len + (loc->value.len - uc->url.len) + 1; if (!(location->value.data = ngx_palloc(r->pool, location->value.len))) { diff --git a/src/http/modules/proxy/ngx_http_proxy_parse.c b/src/http/modules/proxy/ngx_http_proxy_parse.c index 3718ab050..c10cf4924 100644 --- a/src/http/modules/proxy/ngx_http_proxy_parse.c +++ b/src/http/modules/proxy/ngx_http_proxy_parse.c @@ -155,6 +155,9 @@ int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p) case ' ': state = sw_status_text; break; + case '.': /* IIS may send 403.1, 403.2, etc */ + state = sw_status_text; + break; case CR: state = sw_almost_done; break; diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c index c1a8fb621..be5d69a22 100644 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -115,6 +115,7 @@ int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p) static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) { size_t len; + ngx_int_t escape; ngx_uint_t i; ngx_buf_t *b; ngx_chain_t *chain; @@ -133,14 +134,20 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) len = r->method_name.len; } + if (r->quoted_uri) { + escape = 2 * ngx_escape_uri(NULL, r->uri.data + uc->location->len, + r->uri.len - uc->location->len); + } else { + escape = 0; + } + len += uc->uri.len - + r->uri.len - uc->location->len + + r->uri.len - uc->location->len + escape + 1 + r->args.len /* 1 is for "?" */ + sizeof(http_version) - 1 + sizeof(connection_close_header) - 1 + 2; /* 2 is for "\r\n" at the header end */ - if (p->lcf->preserve_host && r->headers_in.host) { len += sizeof(host_header) - 1 + r->headers_in.host_name_len @@ -218,9 +225,16 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) b->last = ngx_cpymem(b->last, uc->uri.data, uc->uri.len); - b->last = ngx_cpymem(b->last, - r->uri.data + uc->location->len, - r->uri.len - uc->location->len); + if (escape) { + ngx_escape_uri(b->last, r->uri.data + uc->location->len, + r->uri.len - uc->location->len); + b->last += r->uri.len - uc->location->len + escape; + + } else { + b->last = ngx_cpymem(b->last, + r->uri.data + uc->location->len, + r->uri.len - uc->location->len); + } if (r->args.len > 0) { *(b->last++) = '?'; @@ -422,7 +436,7 @@ static void ngx_http_proxy_init_upstream(void *data) p->upstream->output_chain_ctx = output; - output->sendfile = r->sendfile; + output->sendfile = r->connection->sendfile; output->pool = r->pool; output->bufs.num = 1; output->tag = (ngx_buf_tag_t) &ngx_http_proxy_module; @@ -737,8 +751,7 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) if (rc == NGX_AGAIN) { ngx_add_timer(c->write, p->lcf->send_timeout); - c->write->available = /* STUB: lowat */ 0; - if (ngx_handle_write_event(c->write, NGX_LOWAT_EVENT) == NGX_ERROR) { + if (ngx_handle_write_event(c->write, p->lcf->send_lowat) == NGX_ERROR) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -1172,6 +1185,7 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) r = p->request; r->headers_out.status = p->upstream->status; + r->headers_out.status_line = p->upstream->status_line; #if 0 r->headers_out.content_length_n = -1; @@ -1298,11 +1312,10 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p) */ ep->cyclic_temp_file = 1; - r->sendfile = 0; + r->connection->sendfile = 0; } else { ep->cyclic_temp_file = 0; - r->sendfile = 1; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); diff --git a/src/http/ngx_http_copy_filter.c b/src/http/ngx_http_copy_filter.c index d015c2144..10c574f4a 100644 --- a/src/http/ngx_http_copy_filter.c +++ b/src/http/ngx_http_copy_filter.c @@ -79,7 +79,7 @@ ngx_int_t ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) ngx_http_create_ctx(r, ctx, ngx_http_copy_filter_module, sizeof(ngx_output_chain_ctx_t), NGX_ERROR); - ctx->sendfile = r->sendfile; + ctx->sendfile = r->connection->sendfile; ctx->need_in_memory = r->filter_need_in_memory; ctx->need_in_temp = r->filter_need_temporary; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 6df6edf45..58021e80a 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -204,6 +204,13 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, tcp_nopush), NULL }, + { ngx_string("tcp_nodelay"), + 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, tcp_nodelay), + 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, @@ -505,11 +512,11 @@ ngx_int_t ngx_http_find_location_config(ngx_http_request_t *r) r->connection->log->log_level = clcf->err_log->log_level; } - if (!(ngx_io.flags & NGX_IO_SENDFILE) || !clcf->sendfile) { - r->sendfile = 0; + if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) { + r->connection->sendfile = 1; } else { - r->sendfile = 1; + r->connection->sendfile = 0; } if (!clcf->tcp_nopush) { @@ -1387,6 +1394,7 @@ static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf) lcf->client_body_timeout = NGX_CONF_UNSET_MSEC; lcf->sendfile = NGX_CONF_UNSET; lcf->tcp_nopush = NGX_CONF_UNSET; + lcf->tcp_nodelay = NGX_CONF_UNSET; lcf->send_timeout = NGX_CONF_UNSET_MSEC; lcf->send_lowat = NGX_CONF_UNSET_SIZE; lcf->postpone_output = NGX_CONF_UNSET_SIZE; @@ -1477,6 +1485,7 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf, prev->client_body_timeout, 60000); ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0); + ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 0); ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000); ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0); ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output, @@ -1795,10 +1804,10 @@ static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data) { -#if (HAVE_LOWAT_EVENT) - ssize_t *np = data; +#if __FreeBSD__ + if (*np >= ngx_freebsd_net_inet_tcp_sendspace) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"send_lowat\" must be less than %d " @@ -1808,11 +1817,13 @@ static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data) return NGX_CONF_ERROR; } -#else +#elif !(HAVE_SO_SNDLOWAT) ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"send_lowat\" is not supported, ignored"); + *np = 0; + #endif return NGX_CONF_OK; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 7468db59c..787f8b8fb 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -172,6 +172,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t sendfile; /* sendfile */ ngx_flag_t tcp_nopush; /* tcp_nopush */ + ngx_flag_t tcp_nodelay; /* tcp_nodelay */ ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ ngx_flag_t msie_padding; /* msie_padding */ diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c index 9876a05da..5b7f3eb27 100644 --- a/src/http/ngx_http_header_filter.c +++ b/src/http/ngx_http_header_filter.c @@ -150,6 +150,7 @@ static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r) len = sizeof("HTTP/1.x ") - 1 + 2 + 2; /* status line */ + if (r->headers_out.status_line.len) { len += r->headers_out.status_line.len; #if (NGX_SUPPRESS_WARN) diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index ba77ffb62..e70a6ea93 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -217,10 +217,13 @@ ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) state = sw_http_09; break; case '.': - case '%': r->complex_uri = 1; state = sw_uri; break; + case '%': + r->quoted_uri = 1; + state = sw_uri; + break; case '/': r->complex_uri = 1; break; @@ -259,7 +262,7 @@ ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) state = sw_after_slash_in_uri; break; case '%': - r->complex_uri = 1; + r->quoted_uri = 1; state = sw_uri; break; case '?': @@ -522,7 +525,7 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b) break; } - /* IIS can send duplicate "HTTP/1.1 ..." lines */ + /* IIS may send the duplicate "HTTP/1.1 ..." lines */ if (ch == '/' && r->proxy && p - r->header_start == 5 diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index e889449ae..6069847f5 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -550,7 +550,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev) return; } - if (r->complex_uri) { + if (r->complex_uri || r->quoted_uri) { rc = ngx_http_parse_complex_uri(r); if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { @@ -1318,8 +1318,7 @@ static void ngx_http_set_write_handler(ngx_http_request_t *r) ngx_add_timer(wev, clcf->send_timeout); } - wev->available = clcf->send_lowat; - if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) { + if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); } @@ -1354,9 +1353,7 @@ void ngx_http_writer(ngx_event_t *wev) ngx_http_core_module); ngx_add_timer(wev, clcf->send_timeout); - wev->available = clcf->send_lowat; - - if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) { + if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); } @@ -1371,9 +1368,8 @@ void ngx_http_writer(ngx_event_t *wev) clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r, ngx_http_core_module); - wev->available = clcf->send_lowat; - if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) { + if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); } @@ -1394,9 +1390,7 @@ void ngx_http_writer(ngx_event_t *wev) ngx_add_timer(wev, clcf->send_timeout); } - wev->available = clcf->send_lowat; - - if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) { + if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); } @@ -1541,6 +1535,7 @@ static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r) static void ngx_http_set_keepalive(ngx_http_request_t *r) { + int tcp_nodelay; ngx_int_t i; ngx_buf_t *b, *f; ngx_event_t *rev, *wev; @@ -1684,7 +1679,26 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) ngx_http_close_connection(c); return; } + c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + + } else { + if (clcf->tcp_nodelay && !c->tcp_nodelay) { + tcp_nodelay = 1; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_close_connection(c); + return; + } + + c->tcp_nodelay = 1; + } } #if 0 @@ -2055,6 +2069,18 @@ void ngx_http_close_connection(ngx_connection_t *c) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "close http connection: %d", c->fd); +#if (NGX_OPENSSL) + + if (c->ssl) { + if (ngx_ssl_shutdown(c) == NGX_AGAIN) { + c->read->event_handler = ngx_ssl_close_handler; + c->write->event_handler = ngx_ssl_close_handler; + return; + } + } + +#endif + #if (NGX_STAT_STUB) (*ngx_stat_active)--; #endif diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index ef169f587..022b8a8cf 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -307,8 +307,10 @@ struct ngx_http_request_s { /* URI is not started with '/' - "GET http://" */ unsigned unusual_uri:1; #endif - /* URI with "/.", "%" and on Win32 with "//" */ + /* URI with "/." and on Win32 with "//" */ unsigned complex_uri:1; + /* URI with "%" */ + unsigned quoted_uri:1; unsigned header_timeout_set:1; unsigned proxy:1; @@ -320,9 +322,6 @@ struct ngx_http_request_s { #endif unsigned pipeline:1; - /* can we use sendfile ? */ - unsigned sendfile:1; - unsigned plain_http:1; unsigned chunked:1; unsigned header_only:1; |