# HG changeset patch # User Igor Sysoev # Date 1111953600 -14400 # Node ID bcb5fce0b038e5ebc4c2fff1b3f5a2d30545f1a7 # Parent b6565ddf033b979cba81b4bced74efcdce65d18e nginx 0.1.27 *) Feature: the "blocked" parameter of the "valid_referers" directive. *) Change: the errors while handling the request header now logged at "info" level. The server name and the "Host" and "Referer" header lines also logged. *) Change: the "Host" header line is also logged in error log. *) Feature: the proxy_pass_unparsed_uri directive. The special handling of the "://" symbols in URI, appeared in 0.1.11 version, now is canceled. *) Bugfix: nginx could not be built on FreeBSD and Linux, if the --without-ngx_http_auth_basic_module configuration parameter was used. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,10 +1,29 @@ + +Changes with nginx 0.1.27 28 Mar 2005 + + *) Feature: the "blocked" parameter of the "invalid_referers" directive. + + *) Change: the errors while handling the request header now logged at + "info" level. The server name and the "Host" and "Referer" header + lines also logged. + + *) Change: the "Host" header line is also logged in error log. + + *) Feature: the proxy_pass_unparsed_uri directive. The special handling + of the "://" symbols in URI, appeared in 0.1.11 version, now is + canceled. + + *) Bugfix: nginx could not be built on FreeBSD and Linux, if the + --without-ngx_http_auth_basic_module configuration parameter was + used. + Changes with nginx 0.1.26 22 Mar 2005 *) Change: the invalid client header lines are now ignored and logged at the info level. - *) Change: the host name is also logged in error log. + *) Change: the server name is also logged in error log. *) Feature: the ngx_http_auth_basic_module module and the auth_basic and auth_basic_user_file directives. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,11 +1,29 @@ + +Изменения в nginx 0.1.27 28.03.2005 + + *) Добавление: параметр blocked в директиве invalid_referers. + + *) Изменение: ошибки обработки заголовка запроса теперь записываются на + уровне info, в лог также записывается имя сервера и строки заголовка + запроса "Host" и "Referer". + + *) Изменение: при записи ошибок в лог записывается также строка + заголовка запроса "Host". + + *) Добавление: директива proxy_pass_unparsed_uri. Специальная обработка + символов "://" в URI, введённая в версии 0.1.11, теперь упразднена. + + *) Исправление: nginx не собирался на FreeBSD и Linux, если был указан + параметр конфигурации --without-ngx_http_auth_basic_module. + Изменения в nginx 0.1.26 22.03.2005 *) Изменение: неверные строки заголовка, переданные клиентом, теперь игнорируется и записываются в error_log на уровне info. - *) Изменение: при записи ошибок в лог записывается так же имя хоста, - при обращении к которому, произошла ошибка. + *) Изменение: при записи ошибок в лог записывается также имя сервера, + при обращении к которому произошла ошибка. *) Добавление: модуль ngx_http_auth_basic_module и директивы auth_basic и auth_basic_user_file. diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -106,6 +106,7 @@ HTTP_MODULES="$HTTP_MODULES $HTTP_INDEX_ if [ $HTTP_AUTH_BASIC = YES ]; then have=NGX_HTTP_AUTH_BASIC . auto/have + have=NGX_CRYPT . auto/have HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_BASIC_MODULE" HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_BASIC_SRCS" CORE_LIBS="$CORE_LIBS $CRYPT_LIB" diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -282,7 +282,7 @@ ngx_add_inherited_sockets(ngx_cycle_t *c if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " - NGINX_VAR " enviroment variable, " + NGINX_VAR " environment variable, " "ignoring the rest of the variable", v); break; } diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.1.26" +#define NGINX_VER "nginx/0.1.27" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -36,6 +36,7 @@ typedef struct { ngx_flag_t log; ngx_flag_t no_referer; + ngx_flag_t blocked_referer; } ngx_http_rewrite_loc_conf_t; @@ -378,6 +379,7 @@ ngx_http_rewrite_regex_start_code(ngx_ht if (code->uri) { if (!code->break_cycle) { r->uri_changed = 1; + r->valid_unparsed_uri = 1; } if (rc && (r->quoted_uri || r->plus_in_uri)) { @@ -715,6 +717,7 @@ ngx_http_rewrite_invalid_referer_code(ng e->sp++; return; + } else { e->sp->value = 1; e->sp->text.len = 1; @@ -731,12 +734,22 @@ ngx_http_rewrite_invalid_referer_code(ng if (len < sizeof("http://i.ru") - 1 || (ngx_strncasecmp(ref, "http://", 7) != 0)) { - e->sp->value = 1; - e->sp->text.len = 1; - e->sp->text.data = (u_char *) "1"; - e->sp++; + if (cf->blocked_referer) { + e->sp->value = 0; + e->sp->text.len = 0; + e->sp->text.data = (u_char *) "0"; + e->sp++; + + return; - return; + } else { + e->sp->value = 1; + e->sp->text.len = 1; + e->sp->text.data = (u_char *) "1"; + e->sp++; + + return; + } } len -= 7; @@ -853,6 +866,7 @@ ngx_http_rewrite_create_loc_conf(ngx_con conf->stack_size = NGX_CONF_UNSET_UINT; conf->log = NGX_CONF_UNSET; conf->no_referer = NGX_CONF_UNSET; + conf->blocked_referer = NGX_CONF_UNSET; return conf; } @@ -873,12 +887,17 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf if (conf->referers == NULL) { conf->referers = prev->referers; ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); + ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); } if (conf->no_referer == NGX_CONF_UNSET) { conf->no_referer = 0; } + if (conf->blocked_referer == NGX_CONF_UNSET) { + conf->blocked_referer = 0; + } + if (conf->codes == NULL) { return NGX_CONF_OK; } @@ -1540,6 +1559,11 @@ ngx_http_rewrite_valid_referers(ngx_conf continue; } + if (ngx_strcmp(value[i].data, "blocked") == 0) { + lcf->blocked_referer = 1; + continue; + } + if (ngx_strcmp(value[i].data, "server_names") == 0) { server_names = 1; continue; diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -107,6 +107,13 @@ static ngx_command_t ngx_http_proxy_com offsetof(ngx_http_proxy_loc_conf_t, preserve_host), NULL }, + { ngx_string("proxy_pass_unparsed_uri"), + 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_proxy_loc_conf_t, pass_unparsed_uri), + NULL }, + { ngx_string("proxy_set_x_url"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -802,7 +809,6 @@ u_char *ngx_http_proxy_log_error(ngx_log { u_char *p; ngx_int_t escape; - ngx_str_t uri; ngx_http_request_t *r; ngx_peer_connection_t *peer; ngx_http_proxy_log_ctx_t *ctx; @@ -814,7 +820,7 @@ u_char *ngx_http_proxy_log_error(ngx_log peer = &ctx->proxy->upstream->peer; p = ngx_snprintf(buf, len, - " while %s, client: %V, host: %V, URL: \"%V\"," + " while %s, client: %V, server: %V, URL: \"%V\"," " upstream: http://%V%s%V", ctx->proxy->action, &r->connection->addr_text, @@ -826,6 +832,13 @@ u_char *ngx_http_proxy_log_error(ngx_log len -= p - buf; buf = p; + if (ctx->proxy->lcf->pass_unparsed_uri && r->valid_unparsed_uri) { + p = ngx_cpymem(buf, r->unparsed_uri.data + 1, r->unparsed_uri.len - 1); + len -= p - buf; + + return ngx_http_log_error_info(r, p, len); + } + if (r->quoted_uri) { escape = 2 * ngx_escape_uri(NULL, r->uri.data + uc->location->len, r->uri.len - uc->location->len, @@ -841,14 +854,15 @@ u_char *ngx_http_proxy_log_error(ngx_log r->uri.len - uc->location->len, NGX_ESCAPE_URI); buf += r->uri.len - uc->location->len + escape; + len -= r->uri.len - uc->location->len + escape; - if (r->args.len == 0) { - return buf; + if (r->args.len) { + p = ngx_snprintf(buf, len, "?%V", &r->args); + len -= p - buf; + buf = p; } - len -= r->uri.len - uc->location->len + escape; - - return ngx_snprintf(buf, len, "?%V", &r->args); + return ngx_http_log_error_info(r, buf, len); } p = ngx_palloc(r->pool, r->uri.len - uc->location->len + escape); @@ -859,17 +873,23 @@ u_char *ngx_http_proxy_log_error(ngx_log ngx_escape_uri(p, r->uri.data + uc->location->len, r->uri.len - uc->location->len, NGX_ESCAPE_URI); - uri.len = r->uri.len - uc->location->len + escape; - uri.data = p; + p = ngx_cpymem(buf, p, r->uri.len - uc->location->len + escape); } else { - uri.len = r->uri.len - uc->location->len; - uri.data = r->uri.data + uc->location->len; - + p = ngx_cpymem(buf, r->uri.data + uc->location->len, + r->uri.len - uc->location->len); } - return ngx_snprintf(buf, len, "%V%s%V", - &uri, r->args.len ? "?" : "", &r->args); + len -= p - buf; + buf = p; + + if (r->args.len) { + p = ngx_snprintf(buf, len, "?%V", &r->args); + len -= p - buf; + buf = p; + } + + return ngx_http_log_error_info(r, buf, len); } @@ -1109,6 +1129,7 @@ static void *ngx_http_proxy_create_loc_c conf->send_timeout = NGX_CONF_UNSET_MSEC; conf->send_lowat = NGX_CONF_UNSET_SIZE; + conf->pass_unparsed_uri = NGX_CONF_UNSET; conf->preserve_host = NGX_CONF_UNSET; conf->set_x_url = NGX_CONF_UNSET; conf->set_x_real_ip = NGX_CONF_UNSET; @@ -1149,6 +1170,15 @@ static char *ngx_http_proxy_merge_loc_co 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->pass_unparsed_uri, prev->pass_unparsed_uri, 0); + + if (conf->pass_unparsed_uri && conf->upstream->location->len > 1) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "\"proxy_pass_unparsed_uri\" can be set for " + "location \"/\" or given by regular expression."); + return NGX_CONF_ERROR; + } + ngx_conf_merge_value(conf->preserve_host, prev->preserve_host, 0); ngx_conf_merge_value(conf->set_x_url, prev->set_x_url, 0); ngx_conf_merge_value(conf->set_x_real_ip, prev->set_x_real_ip, 0); diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -80,6 +80,7 @@ typedef struct { ngx_flag_t set_x_url; ngx_flag_t set_x_real_ip; ngx_flag_t add_x_forwarded_for; + ngx_flag_t pass_unparsed_uri; ngx_flag_t pass_server; ngx_flag_t pass_x_accel_expires; ngx_flag_t ignore_expires; diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -86,7 +86,7 @@ int ngx_http_proxy_request_upstream(ngx_ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) { - size_t len, loc_len; + size_t len; ngx_uint_t i, escape, *index; ngx_buf_t *b; ngx_chain_t *chain; @@ -95,7 +95,6 @@ static ngx_chain_t *ngx_http_proxy_creat ngx_http_request_t *r; ngx_http_variable_t *var; ngx_http_variable_value_t *value; - ngx_http_core_loc_conf_t *clcf; ngx_http_core_main_conf_t *cmcf; ngx_http_proxy_upstream_conf_t *uc; @@ -107,32 +106,30 @@ static ngx_chain_t *ngx_http_proxy_creat index = NULL; #endif + escape = 0; + if (p->upstream->method) { - len = http_methods[p->upstream->method - 1].len; + len = http_methods[p->upstream->method - 1].len + uc->uri.len; } else { - len = r->method_name.len; + len = r->method_name.len + uc->uri.len; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (p->lcf->pass_unparsed_uri && r->valid_unparsed_uri) { + len += r->unparsed_uri.len - 1; -#if (NGX_PCRE) - loc_len = (clcf->regex) ? 1 : clcf->name.len; -#else - loc_len = clcf->name.len; -#endif + } else { + if (r->quoted_uri) { + escape = 2 * ngx_escape_uri(NULL, r->uri.data + uc->location->len, + r->uri.len - uc->location->len, + NGX_ESCAPE_URI); + } - if (r->quoted_uri) { - escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len, - r->uri.len - loc_len, NGX_ESCAPE_URI); - } else { - escape = 0; + len += r->uri.len - uc->location->len + escape + + sizeof("?") - 1 + r->args.len; } - len += uc->uri.len - + r->uri.len - loc_len + escape - + sizeof("?") - 1 + r->args.len - + sizeof(http_version) - 1 + len += sizeof(http_version) - 1 + sizeof(connection_close_header) - 1 + sizeof(CRLF) - 1; @@ -269,19 +266,24 @@ static ngx_chain_t *ngx_http_proxy_creat b->last = ngx_cpymem(b->last, uc->uri.data, uc->uri.len); - if (escape) { - ngx_escape_uri(b->last, r->uri.data + loc_len, - r->uri.len - loc_len, NGX_ESCAPE_URI); - b->last += r->uri.len - loc_len + escape; - + if (p->lcf->pass_unparsed_uri && r->valid_unparsed_uri) { + b->last = ngx_cpymem(b->last, r->unparsed_uri.data + 1, + r->unparsed_uri.len - 1); } else { - b->last = ngx_cpymem(b->last, r->uri.data + loc_len, - r->uri.len - loc_len); - } + if (escape) { + ngx_escape_uri(b->last, r->uri.data + uc->location->len, + r->uri.len - uc->location->len, NGX_ESCAPE_URI); + b->last += r->uri.len - uc->location->len + escape; - if (r->args.len > 0) { - *b->last++ = '?'; - b->last = ngx_cpymem(b->last, r->args.data, r->args.len); + } 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++ = '?'; + b->last = ngx_cpymem(b->last, r->args.data, r->args.len); + } } b->last = ngx_cpymem(b->last, http_version, sizeof(http_version) - 1); diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -68,6 +68,8 @@ void ngx_http_empty_handler(ngx_event_t ngx_int_t ngx_http_send_last(ngx_http_request_t *r); void ngx_http_close_request(ngx_http_request_t *r, int error); void ngx_http_close_connection(ngx_connection_t *c); +u_char * ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, + size_t len); ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -415,8 +415,10 @@ ngx_http_handler(ngx_http_request_t *r) r->connection->write->event_handler = ngx_http_core_phase_event_handler; + r->valid_unparsed_uri = 1; r->uri_changed = 1; r->uri_changes = 11; + r->phase = NGX_HTTP_REWRITE_PHASE; r->phase_handler = 0; diff --git a/src/http/ngx_http_log_module.c b/src/http/ngx_http_log_module.c --- a/src/http/ngx_http_log_module.c +++ b/src/http/ngx_http_log_module.c @@ -544,9 +544,9 @@ ngx_http_log_header_out_getlen(ngx_http_ /* * No header pointer was found. * However, some headers: "Date", "Server", "Content-Length", - * and "Last-Modified" have a special handling in the header filter - * but we do not set up their pointers in the filter because - * they are too seldom needed to be logged. + * and "Last-Modified" have a special handling in the header filter, + * but we do not set up their pointers in the filter, + * because they are too seldom needed to be logged. */ if (data == offsetof(ngx_http_headers_out_t, date)) { @@ -592,9 +592,9 @@ ngx_http_log_header_out(ngx_http_request /* * No header pointer was found. * However, some headers: "Date", "Server", "Content-Length", - * and "Last-Modified" have a special handling in the header filter - * but we do not set up their pointers in the filter because - * they are too seldom needed to be logged. + * and "Last-Modified" have a special handling in the header filter, + * but we do not set up their pointers in the filter, + * because they are too seldom needed to be logged. */ if (op->data == offsetof(ngx_http_headers_out_t, date)) { diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -705,8 +705,6 @@ ngx_int_t ngx_http_parse_complex_uri(ngx u_char c, ch, decoded, *p, *u; enum { sw_usual = 0, - sw_colon, - sw_colon_slash, sw_slash, sw_dot, sw_dot_dot, @@ -774,10 +772,6 @@ ngx_int_t ngx_http_parse_complex_uri(ngx case '?': r->args_start = p; goto done; - case ':': - state = sw_colon; - *u++ = ch; - break; case '.': r->uri_ext = u + 1; *u++ = ch; @@ -789,67 +783,6 @@ ngx_int_t ngx_http_parse_complex_uri(ngx ch = *p++; break; - case sw_colon: - switch(ch) { -#if (NGX_WIN32) - case '\\': - state = sw_colon_slash; - *u++ = '/'; - break; -#endif - case '/': - state = sw_colon_slash; - *u++ = ch; - break; - case ':': - *u++ = ch; - break; - case '%': - quoted_state = state; - state = sw_quoted; - break; - case '?': - r->args_start = p; - goto done; - default: - state = sw_usual; - *u++ = ch; - break; - } - ch = *p++; - break; - - case sw_colon_slash: - switch(ch) { -#if (NGX_WIN32) - case '\\': - state = sw_slash; - *u++ = '/'; - break; -#endif - case '/': - state = sw_slash; - *u++ = ch; - break; - case '.': - state = sw_dot; - *u++ = ch; - break; - case '%': - quoted_state = state; - state = sw_quoted; - break; - case '?': - r->args_start = p; - goto done; - default: - state = sw_usual; - *u++ = ch; - break; - } - ch = *p++; - break; - case sw_slash: switch(ch) { #if (NGX_WIN32) diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -33,24 +33,19 @@ static void ngx_http_keepalive_handler(n static void ngx_http_set_lingering_close(ngx_http_request_t *r); static void ngx_http_lingering_close_handler(ngx_event_t *ev); -static void ngx_http_client_error(ngx_http_request_t *r, - int client_error, int error); static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len); -/* NGX_HTTP_PARSE_... errors */ - -static char *client_header_errors[] = { - "client %V sent invalid method \"%V\"", - "client %V sent invalid request \"%V\"", - "client %V sent too long URI in request \"%V\"", - "client %V sent invalid method in HTTP/0.9 request \"%V\"", - - "client %V sent invalid header, URL: \"%V\"", - "client %V sent too long header line, URL: \"%V\"", - "client %V sent HTTP/1.1 request without \"Host\" header, URL: \"%V\"", - "client %V sent invalid \"Content-Length\" header, URL: \"%V\"", - "client %V sent POST method without \"Content-Length\" header, URL: \"%V\"", +static char *ngx_http_client_errors[] = { + + /* NGX_HTTP_PARSE_INVALID_METHOD */ + "client sent invalid method", + + /* NGX_HTTP_PARSE_INVALID_REQUEST */ + "client sent invalid request", + + /* NGX_HTTP_PARSE_INVALID_09_METHOD */ + "client sent invalid method in HTTP/0.9 request" }; @@ -199,6 +194,7 @@ void ngx_http_init_request(ngx_event_t * ngx_http_request_t *r; ngx_http_in_port_t *in_port; ngx_http_in_addr_t *in_addr; + ngx_http_log_ctx_t *ctx; ngx_http_connection_t *hc; ngx_http_server_name_t *server_name; ngx_http_core_srv_conf_t *cscf; @@ -359,7 +355,7 @@ void ngx_http_init_request(ngx_event_t * /* * The majority of browsers do not send the "close notify" alert. * Among them are MSIE, Mozilla, Netscape 4, Konqueror, and Links. - * And what is more MSIE ignores the server's alert. + * And what is more, MSIE ignores the server's alert. * * Opera always sends the alert. */ @@ -439,6 +435,9 @@ void ngx_http_init_request(ngx_event_t * r->http_state = NGX_HTTP_READING_REQUEST_STATE; + ctx = c->log->data; + ctx->request = r; + #if (NGX_STAT_STUB) ngx_atomic_inc(ngx_stat_reading); r->stat_reading = 1; @@ -467,7 +466,10 @@ ngx_http_ssl_handshake(ngx_event_t *rev) "http check ssl handshake"); if (rev->timedout) { - ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_close_connection(c); return; } @@ -528,7 +530,10 @@ ngx_http_process_request_line(ngx_event_ "http process request line"); if (rev->timedout) { - ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_close_connection(c); return; } @@ -572,14 +577,10 @@ ngx_http_process_request_line(ngx_event_ 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) { - ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); + if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid request"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } @@ -632,9 +633,6 @@ ngx_http_process_request_line(ngx_event_ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http exten: \"%V\"", &r->exten); - ctx = c->log->data; - ctx->request = r; - if (r->http_version < NGX_HTTP_VERSION_10) { rev->event_handler = ngx_http_block_read; ngx_http_handler(r); @@ -665,33 +663,15 @@ ngx_http_process_request_line(ngx_event_ ngx_http_process_request_headers(rev); return; - - } else if (rc != NGX_AGAIN) { + } + + if (rc != NGX_AGAIN) { /* there was error while a request line parsing */ - ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); - -#if 0 - for (p = r->request_start; p < r->header_in->last; p++) { - if (*p == CR || *p == LF) { - break; - } - } - - r->request_line.len = p - r->request_start; - r->request_line.data = r->request_start; - - if (rc == NGX_HTTP_PARSE_INVALID_METHOD) { - r->http_version = NGX_HTTP_VERSION_10; - } - - ngx_http_client_error(r, rc, - (rc == NGX_HTTP_PARSE_INVALID_METHOD) ? - NGX_HTTP_NOT_IMPLEMENTED: - NGX_HTTP_BAD_REQUEST); -#endif - + ngx_log_error(NGX_LOG_INFO, c->log, 0, + ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } @@ -708,8 +688,15 @@ ngx_http_process_request_line(ngx_event_ } if (rv == NGX_DECLINED) { - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI, - NGX_HTTP_REQUEST_URI_TOO_LARGE); + ctx = c->log->data; + ctx->request = r; + + r->request_line.len = r->header_in->end - r->request_start; + r->request_line.data = r->request_start; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent too long URI"); + ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); return; } } @@ -734,7 +721,10 @@ ngx_http_process_request_headers(ngx_eve "http process request header line"); if (rev->timedout) { - ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + c->timedout = 1; + ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_close_connection(c); return; } @@ -755,8 +745,13 @@ ngx_http_process_request_headers(ngx_eve } if (rv == NGX_DECLINED) { - ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER, - NGX_HTTP_BAD_REQUEST); + header.len = r->header_in->end - r->header_name_start; + header.data = r->header_name_start; + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent too long header line: \"%V\"", + &header); + ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + ngx_http_close_connection(c); return; } } @@ -779,8 +774,8 @@ ngx_http_process_request_headers(ngx_eve header.len = r->header_end - r->header_name_start; header.data = r->header_name_start; - ngx_log_error(NGX_LOG_INFO, rev->log, 0, - "client sent invalid header: \"%V\", ignored,", + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid header line: \"%V\"", &header); continue; } @@ -838,8 +833,9 @@ ngx_http_process_request_headers(ngx_eve &h->key, &h->value); continue; - - } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { + } + + if (rc == NGX_HTTP_PARSE_HEADER_DONE) { /* a whole header has been parsed successfully */ @@ -853,7 +849,6 @@ ngx_http_process_request_headers(ngx_eve rc = ngx_http_process_request_header(r); if (rc != NGX_OK) { - ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); return; } @@ -871,37 +866,25 @@ ngx_http_process_request_headers(ngx_eve rev->event_handler = ngx_http_block_read; ngx_http_handler(r); return; - - } else if (rc != NGX_AGAIN) { - - /* there was error while a header line parsing */ - -#if (NGX_DEBUG) - if (rc == NGX_HTTP_PARSE_INVALID_HEADER - && (rev->log->log_level & NGX_LOG_DEBUG_HTTP)) - { - u_char *p; - for (p = r->header_name_start; - p < r->header_in->last - 1; - p++) - { - if (*p == LF) { - break; - } - } - *p = '\0'; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, - "http invalid header: \"%s\"", - r->header_name_start); - } -#endif - - ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); - return; + } + + if (rc == NGX_AGAIN) { + + /* a header line parsing is still not complete */ + + continue; } - /* NGX_AGAIN: a header line parsing is still not complete */ - + /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */ + + header.len = r->header_end - r->header_name_start; + header.data = r->header_name_start; + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid header line: \"%V\\r...\"", + &header); + ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + ngx_http_close_connection(c); + return; } } @@ -1108,8 +1091,9 @@ ngx_http_alloc_large_header_buffer(ngx_h static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) { - u_char *ua, *user_agent, ch; - size_t len; + size_t len; + u_char *ua, *user_agent, ch; + ngx_http_core_srv_conf_t *cscf; if (r->headers_in.host) { for (len = 0; len < r->headers_in.host->value.len; len++) { @@ -1121,16 +1105,33 @@ ngx_http_process_request_header(ngx_http r->headers_in.host->value.data[len] = ngx_tolower(ch); } + r->headers_in.host_name_len = len; if (ngx_http_find_virtual_server(r) != NGX_OK) { - return NGX_HTTP_PARSE_INVALID_HOST; + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid \"Host\" header"); + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_CLOSE) { + ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + ngx_http_close_connection(r->connection); + return NGX_ERROR; + } + + ngx_http_finalize_request(r, NGX_HTTP_INVALID_HOST); + return NGX_ERROR; } } else { if (r->http_version > NGX_HTTP_VERSION_10) { - return NGX_HTTP_PARSE_NO_HOST_HEADER; + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/1.1 request without \"Host\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; } + r->headers_in.host_name_len = 0; } @@ -1140,16 +1141,25 @@ ngx_http_process_request_header(ngx_http r->headers_in.content_length->value.len); if (r->headers_in.content_length_n == NGX_ERROR) { - return NGX_HTTP_PARSE_INVALID_CL_HEADER; + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid \"Content-Length\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; } } if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n == -1) { - return NGX_HTTP_PARSE_POST_WO_CL_HEADER; + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent POST method without \"Content-Length\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; } if (r->plain_http) { - return NGX_HTTP_PARSE_HTTP_TO_HTTPS; + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent plain HTTP request to HTTPS port"); + ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS); + return NGX_ERROR; } if (r->headers_in.connection) { @@ -1457,7 +1467,11 @@ ngx_http_writer(ngx_event_t *wev) if (wev->timedout) { if (!wev->delayed) { - ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "client timed out"); + c->timedout = 1; + ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_close_connection(c); return; } @@ -2267,105 +2281,11 @@ ngx_http_close_connection(ngx_connection } -static void -ngx_http_client_error(ngx_http_request_t *r, int client_error, int error) -{ - u_char *p; - ngx_http_log_ctx_t *ctx; - ngx_http_core_srv_conf_t *cscf; - - ctx = r->connection->log->data; - - if (error == NGX_HTTP_REQUEST_TIME_OUT) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, NGX_ETIMEDOUT, - "client timed out"); - r->connection->timedout = 1; - ngx_http_close_request(r, error); - ngx_http_close_connection(r->connection); - return; - } - - r->connection->log->handler = NULL; - - if (ctx->request) { - - switch (client_error) { - - case NGX_HTTP_PARSE_INVALID_HOST: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client %V sent invalid \"Host\" header \"%V\", URL: \"%V\"", - ctx->client, &r->headers_in.host->value, - &ctx->request->unparsed_uri); - - error = NGX_HTTP_INVALID_HOST; - - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_CLOSE) { - ngx_http_close_request(r, error); - ngx_http_close_connection(r->connection); - return; - } - - break; - - case NGX_HTTP_PARSE_HTTP_TO_HTTPS: - error = NGX_HTTP_TO_HTTPS; - if (ctx->request->headers_in.referer) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client %V sent plain HTTP request to HTTPS port, " - "URL: \"%V\", referrer \"%V\"", - ctx->client, &ctx->request->unparsed_uri, - &ctx->request->headers_in.referer->value); - - } else { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client %V sent plain HTTP request to HTTPS port, " - "URL: \"%V\"", ctx->client, &ctx->request->unparsed_uri); - } - - break; - - default: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR], - ctx->client, &ctx->request->unparsed_uri); - } - - } else { - - if (error == NGX_HTTP_REQUEST_URI_TOO_LARGE) { - r->request_line.len = r->header_in->end - r->request_start; - r->request_line.data = r->request_start; - - } else { - if (r->request_line.data == NULL) { - for (p = r->request_start; p < r->header_in->last; p++) { - if (*p == CR || *p == LF) { - break; - } - } - - r->request_line.len = p - r->request_start; - r->request_line.data = r->request_start; - } - } - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR], - ctx->client, &r->request_line); - } - - r->connection->log->handler = ngx_http_log_error; - - ngx_http_finalize_request(r, error); -} - - static u_char * ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len) { u_char *p; + ngx_http_request_t *r; ngx_http_log_ctx_t *ctx; p = buf; @@ -2375,29 +2295,71 @@ ngx_http_log_error(ngx_log_t *log, u_cha if (log->action) { p = ngx_snprintf(p, len, " while %s", log->action); len -= p - buf; + buf = p; } - p = ngx_snprintf(p, len, ", client: %V", ctx->client); - - if (ctx->request == NULL) { + p = ngx_snprintf(buf, len, ", client: %V", ctx->client); + + r = ctx->request; + + if (r == NULL) { return p; } len -= p - buf; - - if (ctx->request->server_name.data) { - p = ngx_snprintf(p, len, ", host: %V", &ctx->request->server_name); + buf = p; + + if (r->server_name.data) { + p = ngx_snprintf(buf, len, ", server: %V", &r->server_name); len -= p - buf; + buf = p; } - p = ngx_snprintf(p, len, ", URL: \"%V\"", &ctx->request->unparsed_uri); - - if (ctx->request->headers_in.referer == NULL) { - return p; + if (r->unparsed_uri.data) { + p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri); + len -= p - buf; + buf = p; + + } else { + if (r->request_line.data == NULL && r->request_start) { + for (p = r->request_start; p < r->header_in->last; p++) { + if (*p == CR || *p == LF) { + break; + } + } + + r->request_line.len = p - r->request_start; + r->request_line.data = r->request_start; + } + + if (r->request_line.len) { + p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line); + len -= p - buf; + buf = p; + } } - len -= p - buf; - - return ngx_snprintf(p, len, ", referrer: \"%V\"", - &ctx->request->headers_in.referer->value); + return ngx_http_log_error_info(r, buf, len); } + + +u_char * +ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, size_t len) +{ + u_char *p; + + if (r->headers_in.host) { + p = ngx_snprintf(buf, len, ", host: \"%V\"", + &r->headers_in.host->value); + len -= p - buf; + buf = p; + } + + if (r->headers_in.referer) { + p = ngx_snprintf(buf, len, ", referrer: \"%V\"", + &r->headers_in.referer->value); + buf = p; + } + + return buf; +} diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -32,18 +32,10 @@ #define NGX_HTTP_CLIENT_ERROR 10 #define NGX_HTTP_PARSE_INVALID_METHOD 10 #define NGX_HTTP_PARSE_INVALID_REQUEST 11 -#define NGX_HTTP_PARSE_TOO_LONG_URI 12 -#define NGX_HTTP_PARSE_INVALID_09_METHOD 13 +#define NGX_HTTP_PARSE_INVALID_09_METHOD 12 -#define NGX_HTTP_PARSE_HEADER_ERROR 14 -#define NGX_HTTP_PARSE_INVALID_HEADER 14 -#define NGX_HTTP_PARSE_TOO_LONG_HEADER 15 -#define NGX_HTTP_PARSE_NO_HOST_HEADER 16 -#define NGX_HTTP_PARSE_INVALID_CL_HEADER 17 -#define NGX_HTTP_PARSE_POST_WO_CL_HEADER 18 - -#define NGX_HTTP_PARSE_INVALID_HOST 19 -#define NGX_HTTP_PARSE_HTTP_TO_HTTPS 20 +#define NGX_HTTP_PARSE_HEADER_ERROR 13 +#define NGX_HTTP_PARSE_INVALID_HEADER 13 #define NGX_HTTP_OK 200 @@ -338,6 +330,7 @@ struct ngx_http_request_s { /* URI with "\0" or "%00" */ unsigned zero_in_uri:1; + unsigned valid_unparsed_uri:1; unsigned uri_changed:1; unsigned uri_changes:4; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1136,7 +1136,6 @@ ngx_http_upstream_log_error(ngx_log_t *l { u_char *p; ngx_int_t escape; - ngx_str_t uri; ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_upstream_t *u; @@ -1148,7 +1147,7 @@ ngx_http_upstream_log_error(ngx_log_t *l peer = &u->peer; p = ngx_snprintf(buf, len, - " while %s, client: %V, host: %V, URL: \"%V\"," + " while %s, client: %V, server: %V, URL: \"%V\"," " upstream: %V%V%s%V", log->action, &r->connection->addr_text, @@ -1176,14 +1175,15 @@ ngx_http_upstream_log_error(ngx_log_t *l r->uri.len - u->location->len, NGX_ESCAPE_URI); buf += r->uri.len - u->location->len + escape; + len -= r->uri.len - u->location->len + escape; - if (r->args.len == 0) { - return buf; + if (r->args.len) { + p = ngx_snprintf(buf, len, "?%V", &r->args); + len -= p - buf; + buf = p; } - len -= r->uri.len - u->location->len + escape; - - return ngx_snprintf(buf, len, "?%V", &r->args); + return ngx_http_log_error_info(r, buf, len); } p = ngx_palloc(r->pool, r->uri.len - u->location->len + escape); @@ -1194,17 +1194,23 @@ ngx_http_upstream_log_error(ngx_log_t *l ngx_escape_uri(p, r->uri.data + u->location->len, r->uri.len - u->location->len, NGX_ESCAPE_URI); - uri.len = r->uri.len - u->location->len + escape; - uri.data = p; + p = ngx_cpymem(buf, p, r->uri.len - u->location->len + escape); } else { - uri.len = r->uri.len - u->location->len; - uri.data = r->uri.data + u->location->len; - + p = ngx_cpymem(buf, r->uri.data + u->location->len, + r->uri.len - u->location->len); } - return ngx_snprintf(buf, len, "%V%s%V", - &uri, r->args.len ? "?" : "", &r->args); + len -= p - buf; + buf = p; + + if (r->args.len) { + p = ngx_snprintf(buf, len, "?%V", &r->args); + len -= p - buf; + buf = p; + } + + return ngx_http_log_error_info(r, buf, len); } diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -632,7 +632,14 @@ ngx_master_exit(ngx_cycle_t *cycle) ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exit"); + /* + * we do not destroy cycle->pool here because a signal handler + * that uses cycle->log can be called at this point + */ + +#if 0 ngx_destroy_pool(cycle->pool); +#endif exit(0); } @@ -718,6 +725,10 @@ ngx_worker_process_cycle(ngx_cycle_t *cy * we do not destroy cycle->pool here because a signal handler * that uses cycle->log can be called at this point */ + +#if 0 + ngx_destroy_pool(cycle->pool); +#endif exit(0); } @@ -736,6 +747,11 @@ ngx_worker_process_cycle(ngx_cycle_t *cy * we do not destroy cycle->pool here because a signal handler * that uses cycle->log can be called at this point */ + +#if 0 + ngx_destroy_pool(cycle->pool); +#endif + exit(0); } diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c --- a/src/os/unix/ngx_user.c +++ b/src/os/unix/ngx_user.c @@ -18,6 +18,8 @@ */ +#if (NGX_CRYPT) + #if (NGX_LINUX) ngx_int_t @@ -83,3 +85,5 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, } #endif + +#endif /* NGX_CRYPT */