nginx-0.3.42-RELEASE import
*) Feature: the "bind" option of the "listen" directive in IMAP/POP3
proxy.
*) Bugfix: if the same capture in the "rewrite" directive was used more
then once.
*) Bugfix: the $sent_http_content_type, $sent_http_content_length,
$sent_http_last_modified, $sent_http_connection,
$sent_http_keep_alive, and $sent_http_transfer_encoding variables
were not written to access log.
*) Bugfix: the $sent_http_cache_control returned value of the single
"Cache-Control" response header line.
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index 37266a4..c557314 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -395,7 +395,7 @@
regex->size = sc.size;
regex->args = sc.args;
- if (sc.variables == 0) {
+ if (sc.variables == 0 && !sc.dup_capture) {
regex->lengths = NULL;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 15cb0c3..dba3639 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -734,6 +734,19 @@
ngx_buf_t *b;
ngx_chain_t *cl;
+#if 1
+ b = NULL;
+ for (cl = ctx->out; cl; cl = cl->next) {
+ if (cl->buf == b) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "the same buf was used in ssi");
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
+ b = cl->buf;
+ }
+#endif
+
rc = ngx_http_next_body_filter(r, ctx->out);
if (ctx->busy == NULL) {
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 5c1e0a0..a15b3e3 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -725,8 +725,6 @@
ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
#endif
- ls->ctx = ctx;
-
hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
if (hip == NULL) {
return NGX_CONF_ERROR;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 4a9c208..487fd26 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1328,6 +1328,7 @@
ngx_http_update_location_config(r);
r->internal = 1;
+ r->method = NGX_HTTP_GET;
ngx_http_handler(r);
@@ -2528,6 +2529,7 @@
static ngx_http_method_name_t ngx_methods_names[] = {
{ "GET", (uint32_t) ~NGX_HTTP_GET },
{ "HEAD", (uint32_t) ~NGX_HTTP_HEAD },
+ { "POST", (uint32_t) ~NGX_HTTP_POST },
{ NULL, 0 }
};
diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c
index 20a78a0..76deaa4 100644
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -89,6 +89,22 @@
return NGX_ERROR;
}
+#if 1
+ {
+ ngx_chain_t *cl;
+ ngx_buf_t *b = NULL;
+ for (cl = pr->out; cl; cl = cl->next) {
+ if (cl->buf == b) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "the same buf was used in postponed");
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
+ b = cl->buf;
+ }
+ }
+#endif
+
if (r != r->connection->data || r->postponed->request) {
return NGX_AGAIN;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 615ae75..d801e2c 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -201,11 +201,11 @@
}
-static
-void ngx_http_init_request(ngx_event_t *rev)
+static void
+ngx_http_init_request(ngx_event_t *rev)
{
- ngx_uint_t i;
socklen_t len;
+ ngx_uint_t i;
struct sockaddr_in sin;
ngx_connection_t *c;
ngx_http_request_t *r;
@@ -274,7 +274,7 @@
/* AF_INET only */
- hip = c->servers;
+ hip = c->listening->servers;
hia = hip->addrs;
r->port = hip->port;
@@ -311,7 +311,7 @@
r->in_addr = sin.sin_addr.s_addr;
}
- /* the last in_port->addrs address is "*" */
+ /* the last address is "*" */
for ( /* void */ ; i < hip->naddrs - 1; i++) {
if (hia[i].addr == r->in_addr) {
@@ -1405,6 +1405,12 @@
|| rc == NGX_HTTP_REQUEST_TIME_OUT
|| r->connection->error)
{
+ if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
+ && r->headers_out.status == 0)
+ {
+ r->headers_out.status = NGX_HTTP_CLIENT_CLOSED_REQUEST;
+ }
+
if (ngx_http_post_action(r) == NGX_OK) {
return;
}
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 5a52456..9826ece 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -91,6 +91,14 @@
if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
+ n = sc->source->data[i] - '0';
+
+ if (sc->captures_mask & (1 << n)) {
+ sc->dup_capture = 1;
+ }
+
+ sc->captures_mask |= 1 << n;
+
copy_capture = ngx_http_script_add_code(*sc->lengths,
sizeof(ngx_http_script_copy_capture_code_t),
NULL);
@@ -100,7 +108,8 @@
copy_capture->code = (ngx_http_script_code_pt)
ngx_http_script_copy_capture_len_code;
- copy_capture->n = 2 * (sc->source->data[i] - '0');
+ copy_capture->n = 2 * n;
+
copy_capture = ngx_http_script_add_code(*sc->values,
sizeof(ngx_http_script_copy_capture_code_t),
@@ -110,14 +119,12 @@
}
copy_capture->code = ngx_http_script_copy_capture_code;
- copy_capture->n = sc->source->data[i] - '0';
+ copy_capture->n = 2 * n;
- if (sc->ncaptures < copy_capture->n) {
- sc->ncaptures = copy_capture->n;
+ if (sc->ncaptures < n) {
+ sc->ncaptures = n;
}
- copy_capture->n *= 2;
-
i++;
continue;
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index 3ef4d42..c4aa408 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -47,6 +47,7 @@
ngx_uint_t variables;
ngx_uint_t ncaptures;
+ ngx_uint_t captures_mask;
ngx_uint_t size;
void *main;
@@ -54,6 +55,7 @@
unsigned compile_args:1;
unsigned complete_lengths:1;
unsigned complete_values:1;
+ unsigned dup_capture:1;
unsigned args:1;
} ngx_http_script_compile_t;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 997038c..45e586f 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -170,6 +170,10 @@
ngx_http_upstream_ignore_header_line, 0,
ngx_http_upstream_ignore_header_line, 0, 0 },
+ { ngx_string("Keep-Alive"),
+ ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_ignore_header_line, 0, 0 },
+
{ ngx_string("X-Pad"),
ngx_http_upstream_ignore_header_line, 0,
ngx_http_upstream_ignore_header_line, 0, 0 },
@@ -626,6 +630,8 @@
return;
}
+ r->connection->log->action = "SSL handshaking to upstream";
+
rc = ngx_ssl_handshake(c);
if (rc == NGX_AGAIN) {
@@ -852,7 +858,6 @@
"http upstream send request handler");
if (wev->timedout) {
- c->log->action = "sending request to upstream";
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
return;
}
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 69bfe3a..0f162a7 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -49,6 +49,19 @@
static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+
/*
* TODO:
@@ -59,6 +72,13 @@
* Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
*/
+/*
+ * the $http_host, $http_user_agent, $http_referer, $http_via,
+ * and $http_x_forwarded_for variables may be handled by generic
+ * ngx_http_variable_unknown_header_in(), but for perfomance reasons
+ * they are handled using dedicated entries
+ */
+
static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("http_host"), NULL, ngx_http_variable_header,
@@ -146,6 +166,27 @@
ngx_http_variable_request_completion,
0, 0, 0 },
+ { ngx_string("sent_http_content_type"), NULL,
+ ngx_http_variable_sent_content_type, 0, 0, 0 },
+
+ { ngx_string("sent_http_content_length"), NULL,
+ ngx_http_variable_sent_content_length, 0, 0, 0 },
+
+ { ngx_string("sent_http_last_modified"), NULL,
+ ngx_http_variable_sent_last_modified, 0, 0, 0 },
+
+ { ngx_string("sent_http_connection"), NULL,
+ ngx_http_variable_sent_connection, 0, 0, 0 },
+
+ { ngx_string("sent_http_keep_alive"), NULL,
+ ngx_http_variable_sent_keep_alive, 0, 0, 0 },
+
+ { ngx_string("sent_http_transfer_encoding"), NULL,
+ ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
+
+ { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
+ offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
+
{ ngx_string("limit_rate"), ngx_http_variable_request_set_size,
ngx_http_variable_request,
offsetof(ngx_http_request_t, limit_rate),
@@ -847,6 +888,178 @@
static ngx_int_t
+ngx_http_variable_sent_content_type(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ if (r->headers_out.content_type.len) {
+ v->len = r->headers_out.content_type.len;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = r->headers_out.content_type.data;
+
+ } else {
+ v->not_found = 1;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_variable_sent_content_length(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ u_char *p;
+
+ if (r->headers_out.content_length) {
+ v->len = r->headers_out.content_length->value.len;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = r->headers_out.content_length->value.data;
+
+ return NGX_OK;
+ }
+
+ if (r->headers_out.content_length_n >= 0) {
+ p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = p;
+
+ return NGX_OK;
+ }
+
+ v->not_found = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ u_char *p;
+
+ if (r->headers_out.last_modified) {
+ v->len = r->headers_out.last_modified->value.len;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = r->headers_out.last_modified->value.data;
+
+ return NGX_OK;
+ }
+
+ if (r->headers_out.last_modified_time >= 0) {
+ p = ngx_palloc(r->pool,
+ sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = p;
+
+ return NGX_OK;
+ }
+
+ v->not_found = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_variable_sent_connection(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ size_t len;
+ char *p;
+
+ if (r->keepalive) {
+ len = sizeof("keep-alive") - 1;
+ p = "keep-alive";
+
+ } else {
+ len = sizeof("close") - 1;
+ p = "close";
+ }
+
+ v->len = len;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) p;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ u_char *p;
+ ngx_http_core_loc_conf_t *clcf;
+
+ if (r->keepalive) {
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (clcf->keepalive_header) {
+
+ p = ngx_palloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = p;
+
+ return NGX_OK;
+ }
+ }
+
+ v->not_found = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ if (r->chunked) {
+ v->len = sizeof("chunked") - 1;
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) "chunked";
+
+ } else {
+ v->not_found = 1;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_variable_request_completion(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{