Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2004-10-11 19:07:03 +0400
committerIgor Sysoev <igor@sysoev.ru>2004-10-11 19:07:03 +0400
commit924bd79e317e9a137c0d1b9d349185758a628ec4 (patch)
treef877c8b19e53e7d0a7683e3dd9aeb713146c4a8f /src/http
parentaef13d7f6660f4f8d2c50c95b8e182e62c115f88 (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.c10
-rw-r--r--src/http/modules/ngx_http_gzip_filter.c179
-rw-r--r--src/http/modules/ngx_http_userid_filter.c4
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c99
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.h1
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_header.c20
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_parse.c3
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_upstream.c33
-rw-r--r--src/http/ngx_http_copy_filter.c2
-rw-r--r--src/http/ngx_http_core_module.c23
-rw-r--r--src/http/ngx_http_core_module.h1
-rw-r--r--src/http/ngx_http_header_filter.c1
-rw-r--r--src/http/ngx_http_parse.c9
-rw-r--r--src/http/ngx_http_request.c48
-rw-r--r--src/http/ngx_http_request.h7
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;