# HG changeset patch # User Igor Sysoev # Date 1165957200 -10800 # Node ID 251bcd11a5b8f1652df07507852343961efefbbe # Parent 3d4634b3b321c6497fbaca83c77861e8df958988 nginx 0.5.3 *) Feature: the ngx_http_perl_module supports the $r->status, $r->log_error, and $r->sleep methods. *) Feature: the $r->variable method supports variables that do not exist in nginx configuration. *) Bugfix: the $r->has_request_body method did not work. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,22 @@ +Changes with nginx 0.5.3 13 Dec 2006 + + *) Feature: the ngx_http_perl_module supports the $r->status, + $r->log_error, and $r->sleep methods. + + *) Feature: the $r->variable method supports variables that do not + exist in nginx configuration. + + *) Bugfix: the $r->has_request_body method did work. + + +Changes with nginx 0.5.2 11 Dec 2006 + + *) Bugfix: if the "proxy_pass" directive used the name of the + "upstream" block, then nginx tried to resolve the name; bug appeared + in 0.5.1. + + Changes with nginx 0.5.1 11 Dec 2006 *) Bugfix: the "post_action" directive might not run after a diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,22 @@ +Изменения в nginx 0.5.3 13.12.2006 + + *) Добавление: модуль ngx_http_perl_module поддерживает методы + $r->status, $r->log_error и $r->sleep. + + *) Добавление: метод $r->variable поддерживает переменные, неописанные + в конфигурации nginx'а. + + *) Исправление: метод $r->has_request_body не работал. + + +Изменения в nginx 0.5.2 11.12.2006 + + *) Исправление: если в директивах proxy_pass использовалось имя, + указанное в upstream, то nginx пытался найти IP-адрес этого имени; + ошибка появилась в 0.5.1. + + Изменения в nginx 0.5.1 11.12.2006 *) Исправление: директива post_action могла не работать после 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_VERSION "0.5.2" +#define NGINX_VERSION "0.5.3" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -221,8 +221,8 @@ ngx_ptocidr(ngx_str_t *text, void *cidr) ngx_int_t ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u) { - u_char *p, *host; - size_t len; + u_char *p, *host, *port_start; + size_t len, port_len; ngx_int_t port; ngx_uint_t i; struct hostent *h; @@ -290,8 +290,7 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t u->host.len = len; u->host.data = p; - u->host_header.len = sizeof("localhost") - 1; - u->host_header.data = (u_char *) "localhost"; + u->unix_socket = 1; return NGX_OK; @@ -309,17 +308,18 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t } u->host.data = p; - u->host_header.len = len; - u->host_header.data = p; + + port_start = NULL; + port_len = 0; for (i = 0; i < len; i++) { if (p[i] == ':') { - u->port.data = &p[i + 1]; + port_start = &p[i + 1]; u->host.len = i; if (!u->uri_part) { - u->port.len = len - (i + 1); + port_len = len - (i + 1); break; } } @@ -327,20 +327,19 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t if (p[i] == '/') { u->uri.len = len - i; u->uri.data = &p[i]; - u->host_header.len = i; if (u->host.len == 0) { u->host.len = i; } - if (u->port.data == NULL) { + if (port_start == NULL) { u->no_port = 1; goto no_port; } - u->port.len = &p[i] - u->port.data; + port_len = &p[i] - port_start; - if (u->port.len == 0) { + if (port_len == 0) { u->err = "invalid port"; return NGX_ERROR; } @@ -349,18 +348,18 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t } } - if (u->port.data) { + if (port_start) { - if (u->port.len == 0) { - u->port.len = &p[i] - u->port.data; + if (port_len == 0) { + port_len = &p[i] - port_start; - if (u->port.len == 0) { + if (port_len == 0) { u->err = "invalid port"; return NGX_ERROR; } } - port = ngx_atoi(u->port.data, u->port.len); + port = ngx_atoi(port_start, port_len); if (port == NGX_ERROR || port < 1 || port > 65536) { u->err = "invalid port"; @@ -377,24 +376,22 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t goto no_port; } - u->port.len = len; - u->port.data = p; u->wildcard = 1; } - u->portn = (in_port_t) port; + u->port = (in_port_t) port; no_port: if (u->listen) { - if (u->portn == 0) { - if (u->default_portn == 0) { + if (u->port == 0) { + if (u->default_port == 0) { u->err = "no port"; return NGX_ERROR; } - u->portn = u->default_portn; + u->port = u->default_port; } if (u->host.len == 1 && u->host.data[0] == '*') { @@ -422,7 +419,7 @@ no_port: return NGX_ERROR; } - u->addr.in_addr = *(in_addr_t *)(h->h_addr_list[0]); + u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]); } } else { @@ -432,28 +429,6 @@ no_port: return NGX_OK; } - if (u->no_port) { - - if (u->default_portn == 0 && !u->upstream) { - u->err = "no port"; - return NGX_ERROR; - } - - u->portn = u->default_portn; - - u->port.data = ngx_palloc(cf->pool, sizeof("65536") - 1); - if (u->port.data == NULL) { - return NGX_ERROR; - } - - u->port.len = ngx_sprintf(u->port.data, "%d", u->portn) - u->port.data; - - } else if (u->portn == 0) { - - u->err = "no port"; - return NGX_ERROR; - } - if (u->host.len == 0) { u->err = "no host"; return NGX_ERROR; @@ -463,6 +438,15 @@ no_port: return NGX_OK; } + if (u->no_port) { + u->port = u->default_port; + } + + if (u->port == 0) { + u->err = "no port"; + return NGX_ERROR; + } + if (ngx_inet_resolve_host(cf, u) != NGX_OK) { return NGX_ERROR; } @@ -474,7 +458,7 @@ no_port: ngx_int_t ngx_inet_resolve_host(ngx_conf_t *cf, ngx_url_t *u) { - u_char *host; + u_char *p, *host; size_t len; in_addr_t in_addr; ngx_uint_t i; @@ -524,7 +508,7 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng } sin->sin_family = AF_INET; - sin->sin_port = htons(u->portn); + sin->sin_port = htons(u->port); sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); u->addrs[i].sockaddr = (struct sockaddr *) sin; @@ -532,17 +516,15 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1; - u->addrs[i].name.data = ngx_palloc(cf->pool, len); - if (u->addrs[i].name.data == NULL) { + p = ngx_palloc(cf->pool, len); + if (p == NULL) { return NGX_ERROR; } - len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, - u->addrs[i].name.data, len); + len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, p, len); - u->addrs[i].name.len = ngx_sprintf(&u->addrs[i].name.data[len], - ":%d", u->portn) - - u->addrs[i].name.data; + u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p; + u->addrs[i].name.data = p; } } else { @@ -562,21 +544,19 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng u->naddrs = 1; sin->sin_family = AF_INET; - sin->sin_port = htons(u->portn); + sin->sin_port = htons(u->port); sin->sin_addr.s_addr = in_addr; u->addrs[0].sockaddr = (struct sockaddr *) sin; u->addrs[0].socklen = sizeof(struct sockaddr_in); - u->addrs[0].name.data = ngx_palloc(cf->pool, - u->host.len + sizeof(":65536") - 1); - if (u->addrs[0].name.data == NULL) { + p = ngx_palloc(cf->pool, u->host.len + sizeof(":65536") - 1); + if (p == NULL) { return NGX_ERROR; } - u->addrs[0].name.len = ngx_sprintf(u->addrs[0].name.data, "%V:%d", - &u->host, u->portn) - - u->addrs[0].name.data; + u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p; + u->addrs[0].name.data = p; } return NGX_OK; diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -35,21 +35,19 @@ typedef struct { ngx_str_t url; ngx_str_t host; - ngx_str_t host_header; - ngx_str_t port; ngx_str_t uri; - in_port_t portn; - in_port_t default_portn; + in_port_t port; + in_port_t default_port; unsigned listen:1; unsigned uri_part:1; - unsigned upstream:1; unsigned no_resolve:1; unsigned one_addr:1; unsigned wildcard:1; unsigned no_port:1; + unsigned unix_socket:1; ngx_url_addr_t addr; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2010,7 +2010,6 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ng ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; - u.upstream = 1; u.no_resolve = 1; lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -546,6 +546,8 @@ ngx_http_log_merge_loc_conf(ngx_conf_t * return NGX_CONF_ERROR; } + log->disk_full_time = 0; + lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); fmt = lmcf->formats.elts; diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -583,7 +583,6 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; - u.upstream = 1; u.no_resolve = 1; /* u.uri_part = 1; may be used as namespace */ diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -51,7 +51,7 @@ typedef struct { ngx_str_t method; ngx_str_t host_header; - ngx_str_t port_text; + ngx_str_t port; ngx_flag_t redirect; } ngx_http_proxy_loc_conf_t; @@ -1232,11 +1232,11 @@ ngx_http_proxy_port_variable(ngx_http_re plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); - v->len = plcf->port_text.len; + v->len = plcf->port.len; v->valid = 1; v->no_cachable = 0; v->not_found = 0; - v->data = plcf->port_text.data; + v->data = plcf->port.data; return NGX_OK; } @@ -1817,7 +1817,7 @@ peers: conf->upstream.upstream = prev->upstream.upstream; conf->host_header = prev->host_header; - conf->port_text = prev->port_text; + conf->port = prev->port; conf->upstream.schema = prev->upstream.schema; } @@ -2093,6 +2093,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_ { ngx_http_proxy_loc_conf_t *plcf = conf; + u_char *p; size_t add; u_short port; ngx_str_t *value, *url; @@ -2158,18 +2159,49 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_ u.url.len = url->len - add; u.url.data = url->data + add; - u.default_portn = port; - u.upstream = 1; + u.default_port = port; + u.uri_part = 1; u.no_resolve = 1; - u.uri_part = 1; plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); if (plcf->upstream.upstream == NULL) { return NGX_CONF_ERROR; } - plcf->host_header = u.host_header; - plcf->port_text = u.port; + if (!u.unix_socket) { + if (u.no_port || u.port == port) { + plcf->host_header = u.host; + + if (port == 80) { + plcf->port.len = sizeof("80") - 1; + plcf->port.data = (u_char *) "80"; + } else { + plcf->port.len = sizeof("443") - 1; + plcf->port.data = (u_char *) "443"; + } + + } else { + p = ngx_palloc(cf->pool, u.host.len + sizeof(":65536") - 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + plcf->host_header.len = ngx_sprintf(p, "%V:%d", &u.host, u.port) + - p; + plcf->host_header.data = p; + + plcf->port.len = plcf->host_header.len - u.host.len - 1; + plcf->port.data = p + u.host.len + 1; + } + + + } else { + plcf->host_header.len = sizeof("localhost") - 1; + plcf->host_header.data = (u_char *) "localhost"; + plcf->port.len = 0; + plcf->port.data = (u_char *) ""; + } + plcf->upstream.uri = u.uri; plcf->upstream.schema.len = add; diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -11,26 +11,85 @@ our @ISA = qw(Exporter); our @EXPORT = qw( OK DECLINED + HTTP_OK + HTTP_CREATED + HTTP_NO_CONTENT + HTTP_PARTIAL_CONTENT + + HTTP_MOVED_PERMANENTLY + HTTP_MOVED_TEMPORARILY HTTP_REDIRECT + HTTP_NOT_MODIFIED + + HTTP_BAD_REQUEST + HTTP_UNAUTHORIZED + HTTP_PAYMENT_REQUIRED + HTTP_FORBIDDEN HTTP_NOT_FOUND + HTTP_NOT_ALLOWED + HTTP_NOT_ACCEPTABLE + HTTP_REQUEST_TIME_OUT + HTTP_CONFLICT + HTTP_GONE + HTTP_LENGTH_REQUIRED + HTTP_REQUEST_ENTITY_TOO_LARGE + HTTP_REQUEST_URI_TOO_LARGE + HTTP_UNSUPPORTED_MEDIA_TYPE + HTTP_RANGE_NOT_SATISFIABLE + + HTTP_INTERNAL_SERVER_ERROR HTTP_SERVER_ERROR + HTTP_NOT_IMPLEMENTED + HTTP_BAD_GATEWAY + HTTP_SERVICE_UNAVAILABLE + HTTP_GATEWAY_TIME_OUT + HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.5.2'; +our $VERSION = '0.5.3'; require XSLoader; XSLoader::load('nginx', $VERSION); # Preloaded methods go here. -use constant OK => 0; -use constant DECLINED => -5; +use constant OK => 0; +use constant DECLINED => -5; + +use constant HTTP_OK => 200; +use constant HTTP_CREATED => 201; +use constant HTTP_NO_CONTENT => 204; +use constant HTTP_PARTIAL_CONTENT => 206; + +use constant HTTP_MOVED_PERMANENTLY => 301; +use constant HTTP_MOVED_TEMPORARILY => 302; +use constant HTTP_REDIRECT => 302; +use constant HTTP_NOT_MODIFIED => 304; -use constant HTTP_OK => 200; -use constant HTTP_REDIRECT => 302; -use constant HTTP_NOT_FOUND => 404; -use constant HTTP_SERVER_ERROR => 500; +use constant HTTP_BAD_REQUEST => 400; +use constant HTTP_UNAUTHORIZED => 401; +use constant HTTP_PAYMENT_REQUIRED => 402; +use constant HTTP_FORBIDDEN => 403; +use constant HTTP_NOT_FOUND => 404; +use constant HTTP_NOT_ALLOWED => 405; +use constant HTTP_NOT_ACCEPTABLE => 406; +use constant HTTP_REQUEST_TIME_OUT => 408; +use constant HTTP_CONFLICT => 409; +use constant HTTP_GONE => 410; +use constant HTTP_LENGTH_REQUIRED => 411; +use constant HTTP_REQUEST_ENTITY_TOO_LARGE => 413; +use constant HTTP_REQUEST_URI_TOO_LARGE => 414; +use constant HTTP_UNSUPPORTED_MEDIA_TYPE => 415; +use constant HTTP_RANGE_NOT_SATISFIABLE => 416; + +use constant HTTP_INTERNAL_SERVER_ERROR => 500; +use constant HTTP_SERVER_ERROR => 500; +use constant HTTP_NOT_IMPLEMENTED => 501; +use constant HTTP_BAD_GATEWAY => 502; +use constant HTTP_SERVICE_UNAVAILABLE => 503; +use constant HTTP_GATEWAY_TIME_OUT => 504; +use constant HTTP_INSUFFICIENT_STORAGE => 507; 1; diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -94,6 +94,22 @@ MODULE = nginx PACKAGE = nginx void +status(r, code) + CODE: + + ngx_http_request_t *r; + + ngx_http_perl_set_request(r); + + r->headers_out.status = SvIV(ST(1)); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "perl status: %d", r->headers_out.status); + + XSRETURN_UNDEF; + + +void send_http_header(r, ...) CODE: @@ -334,7 +350,6 @@ has_request_body(r, next) dXSTARG; ngx_http_request_t *r; - SV *next; ngx_http_perl_ctx_t *ctx; ngx_http_perl_set_request(r); @@ -343,10 +358,8 @@ has_request_body(r, next) XSRETURN_UNDEF; } - next = ST(1); - ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); - ctx->next = next; + ctx->next = SvRV(ST(1)); r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; @@ -776,6 +789,8 @@ variable(r, name, value = NULL) STRLEN len; ngx_str_t var, val; ngx_uint_t i, hash; + ngx_http_perl_var_t *v; + ngx_http_perl_ctx_t *ctx; ngx_http_variable_value_t *vv; ngx_http_perl_set_request(r); @@ -817,13 +832,69 @@ variable(r, name, value = NULL) var.len = len; var.data = lowcase; + #if (NGX_LOG_DEBUG) + + if (value) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "perl variable: \"%V\"=\"%V\"", &var, &val); + } else { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "perl variable: \"%V\"", &var); + } + + #endif + vv = ngx_http_get_variable(r, &var, hash, 1); if (vv == NULL) { XSRETURN_UNDEF; } if (vv->not_found) { - if (value == NULL) { + + ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); + + if (ctx->variables) { + + v = ctx->variables->elts; + for (i = 0; i < ctx->variables->nelts; i++) { + + if (hash != v[i].hash + || len != v[i].name.len + || ngx_strncmp(lowcase, v[i].name.data, len) != 0) + { + continue; + } + + if (value) { + v[i].value = val; + XSRETURN_UNDEF; + } + + ngx_http_perl_set_targ(v[i].value.data, v[i].value.len, 0); + + goto done; + } + } + + if (value) { + if (ctx->variables == NULL) { + ctx->variables = ngx_array_create(r->pool, 1, + sizeof(ngx_http_perl_var_t)); + if (ctx->variables == NULL) { + XSRETURN_UNDEF; + } + } + + v = ngx_array_push(ctx->variables); + if (v == NULL) { + XSRETURN_UNDEF; + } + + v->hash = hash; + v->name.len = len; + v->name.data = lowcase; + v->value = val; + XSRETURN_UNDEF; } @@ -845,4 +916,60 @@ variable(r, name, value = NULL) ngx_http_perl_set_targ(vv->data, vv->len, 0); + done: + ST(0) = TARG; + + +void +sleep(r, sleep, next) + CODE: + + dXSTARG; + ngx_http_request_t *r; + ngx_http_perl_ctx_t *ctx; + + ngx_http_perl_set_request(r); + + ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); + + ctx->sleep = SvIV(ST(1)); + ctx->next = SvRV(ST(2)); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "perl sleep: %d", ctx->sleep); + + XSRETURN_EMPTY; + + +void +log_error(r, err, msg) + CODE: + + ngx_http_request_t *r; + SV *err, *msg; + u_char *p; + STRLEN len; + ngx_err_t e; + + ngx_http_perl_set_request(r); + + err = ST(1); + + if (SvROK(err) && SvTYPE(SvRV(err)) == SVt_PV) { + err = SvRV(err); + } + + e = SvIV(err); + + msg = ST(2); + + if (SvROK(msg) && SvTYPE(SvRV(msg)) == SVt_PV) { + msg = SvRV(msg); + } + + p = (u_char *) SvPV(msg, len); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, e, "perl: %s", p); + + XSRETURN_EMPTY; diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -41,6 +41,7 @@ static ngx_int_t ngx_http_perl_ssi(ngx_h ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params); #endif +static void ngx_http_perl_sleep_handler(ngx_http_request_t *r); static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf); static PerlInterpreter * @@ -62,7 +63,6 @@ static char *ngx_http_perl_require(ngx_c void *conf); static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void ngx_http_perl_cleanup_sv(void *data); #if (NGX_HAVE_PERL_MULTIPLICITY) static void ngx_http_perl_cleanup_perl(void *data); @@ -246,6 +246,12 @@ ngx_http_perl_handle_request(ngx_http_re ctx->filename.data = NULL; ctx->redirect_uri.len = 0; + if (ctx->sleep) { + ngx_add_timer(r->connection->write, (ngx_msec_t) ctx->sleep); + r->write_event_handler = ngx_http_perl_sleep_handler; + ctx->sleep = 0; + } + if (ctx->done || ctx->next) { return; } @@ -264,6 +270,28 @@ ngx_http_perl_handle_request(ngx_http_re } +static void +ngx_http_perl_sleep_handler(ngx_http_request_t *r) +{ + ngx_event_t *wev; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "perl sleep handler"); + + wev = r->connection->write; + + if (wev->timedout) { + wev->timedout = 0; + ngx_http_perl_handle_request(r); + return; + } + + if (ngx_handle_write_event(wev, 0) == NGX_ERROR) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + } +} + + static ngx_int_t ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) @@ -758,18 +786,6 @@ ngx_http_perl_cleanup_perl(void *data) #endif -static void -ngx_http_perl_cleanup_sv(void *data) -{ - ngx_http_perl_cleanup_t *cln = data; - - dTHXa(cln->perl); - PERL_SET_CONTEXT(cln->perl); - - SvREFCNT_dec(cln->sv); -} - - static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf) { @@ -860,8 +876,6 @@ ngx_http_perl(ngx_conf_t *cf, ngx_comman ngx_http_perl_loc_conf_t *plcf = conf; ngx_str_t *value; - ngx_pool_cleanup_t *cln; - ngx_http_perl_cleanup_t *pcln; ngx_http_core_loc_conf_t *clcf; ngx_http_perl_main_conf_t *pmcf; @@ -881,11 +895,6 @@ ngx_http_perl(ngx_conf_t *cf, ngx_comman } } - cln = ngx_pool_cleanup_add(cf->pool, sizeof(ngx_http_perl_cleanup_t)); - if (cln == NULL) { - return NGX_CONF_ERROR; - } - plcf->handler = value[1]; { @@ -907,11 +916,6 @@ ngx_http_perl(ngx_conf_t *cf, ngx_comman } - cln->handler = ngx_http_perl_cleanup_sv; - pcln = cln->data; - pcln->sv = plcf->sub; - pcln->perl = pmcf->perl; - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_perl_handler; @@ -924,9 +928,7 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_co { ngx_int_t index; ngx_str_t *value; - ngx_pool_cleanup_t *cln; ngx_http_variable_t *v; - ngx_http_perl_cleanup_t *pcln; ngx_http_perl_variable_t *pv; ngx_http_perl_main_conf_t *pmcf; @@ -964,11 +966,6 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_co } } - cln = ngx_pool_cleanup_add(cf->pool, sizeof(ngx_http_perl_cleanup_t)); - if (cln == NULL) { - return NGX_CONF_ERROR; - } - pv->handler = value[2]; { @@ -990,11 +987,6 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_co } - cln->handler = ngx_http_perl_cleanup_sv; - pcln = cln->data; - pcln->sv = pv->sub; - pcln->perl = pmcf->perl; - v->get_handler = ngx_http_perl_variable; v->data = (uintptr_t) pv; diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h --- a/src/http/modules/perl/ngx_http_perl_module.h +++ b/src/http/modules/perl/ngx_http_perl_module.h @@ -23,16 +23,27 @@ typedef struct { ngx_str_t filename; ngx_str_t redirect_uri; ngx_str_t redirect_args; + SV *next; + int sleep; ngx_uint_t done; /* unsigned done:1; */ + ngx_array_t *variables; /* array of ngx_http_perl_var_t */ + #if (NGX_HTTP_SSI) ngx_http_ssi_ctx_t *ssi; #endif } ngx_http_perl_ctx_t; +typedef struct { + ngx_uint_t hash; + ngx_str_t name; + ngx_str_t value; +} ngx_http_perl_var_t; + + extern ngx_module_t ngx_http_perl_module; 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 @@ -2390,7 +2390,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx u.url = value[1]; u.listen = 1; - u.default_portn = 80; + u.default_port = 80; if (ngx_parse_url(cf, &u) != NGX_OK) { if (u.err) { @@ -2411,7 +2411,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ls->family = AF_INET; ls->addr = u.addr.in_addr; - ls->port = u.portn; + ls->port = u.port; ls->file_name = cf->conf_file->file.name; ls->line = cf->conf_file->line; ls->conf.backlog = -1; 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 @@ -2598,7 +2598,6 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_co value = cf->args->elts; u.host = value[1]; - u.upstream = 1; u.no_resolve = 1; uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE @@ -2722,7 +2721,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; - u.default_portn = 80; + u.default_port = 80; if (ngx_parse_url(cf, &u) != NGX_OK) { if (u.err) { @@ -2843,8 +2842,8 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { - if ((uscfp[i]->port && uscfp[i]->port != u->portn) - || uscfp[i]->host.len != u->host.len + + if (uscfp[i]->host.len != u->host.len || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) != 0) { @@ -2859,10 +2858,23 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng return NULL; } - if (uscfp[i]->port == 0 && u->portn && !u->no_port) { + if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && u->port) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "upstream \"%V\" port %d is ignored", - &u->host, u->portn); + "upstream \"%V\" may not have port %d", + &u->host, u->port); + return NULL; + } + + if ((flags & NGX_HTTP_UPSTREAM_CREATE) && uscfp[i]->port) { + ngx_log_error(NGX_LOG_WARN, cf->log, 0, + "upstream \"%V\" may not have port %d in %s:%ui", + &u->host, uscfp[i]->port, + uscfp[i]->file_name.data, uscfp[i]->line); + return NULL; + } + + if (uscfp[i]->port != u->port) { + continue; } return uscfp[i]; @@ -2877,7 +2889,8 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng uscf->host = u->host; uscf->file_name = cf->conf_file->file.name; uscf->line = cf->conf_file->line; - uscf->port = u->portn; + uscf->port = u->port; + uscf->default_port = u->default_port; if (u->naddrs == 1) { uscf->servers = ngx_array_create(cf->pool, 1, diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -94,6 +94,7 @@ struct ngx_http_upstream_srv_conf_s { ngx_str_t file_name; ngx_uint_t line; in_port_t port; + in_port_t default_port; }; diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -61,10 +61,17 @@ ngx_http_upstream_init_round_robin(ngx_c /* an upstream implicitly defined by proxy_pass, etc. */ + if (us->port == 0 && us->default_port == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no port in upstream \"%V\" in %s:%ui", + &us->host, us->file_name.data, us->line); + return NGX_ERROR; + } + ngx_memzero(&u, sizeof(ngx_url_t)); u.host = us->host; - u.portn = us->port; + u.port = (in_port_t) (us->port ? us->port : us->default_port); if (ngx_inet_resolve_host(cf, &u) != NGX_OK) { if (u.err) { @@ -76,13 +83,6 @@ ngx_http_upstream_init_round_robin(ngx_c return NGX_ERROR; } - if (us->port == 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no port in upstream \"%V\" in %s:%ui", - &us->host, us->file_name.data, us->line); - return NGX_ERROR; - } - n = u.naddrs; peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c --- a/src/imap/ngx_imap_auth_http_module.c +++ b/src/imap/ngx_imap_auth_http_module.c @@ -1291,7 +1291,7 @@ ngx_imap_auth_http(ngx_conf_t *cf, ngx_c ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; - u.default_portn = 80; + u.default_port = 80; u.uri_part = 1; u.one_addr = 1; @@ -1304,7 +1304,7 @@ ngx_imap_auth_http(ngx_conf_t *cf, ngx_c ahcf->peer = u.addrs; - ahcf->host_header = u.host_header; + ahcf->host_header = u.host; ahcf->uri = u.uri; if (ahcf->uri.len == 0) { diff --git a/src/imap/ngx_imap_core_module.c b/src/imap/ngx_imap_core_module.c --- a/src/imap/ngx_imap_core_module.c +++ b/src/imap/ngx_imap_core_module.c @@ -541,7 +541,7 @@ ngx_imap_core_listen(ngx_conf_t *cf, ngx for (i = 0; i < cmcf->listen.nelts; i++) { - if (imls[i].addr != u.addr.in_addr || imls[i].port != u.portn) { + if (imls[i].addr != u.addr.in_addr || imls[i].port != u.port) { continue; } @@ -558,7 +558,7 @@ ngx_imap_core_listen(ngx_conf_t *cf, ngx ngx_memzero(imls, sizeof(ngx_imap_listen_t)); imls->addr = u.addr.in_addr; - imls->port = u.portn; + imls->port = u.port; imls->family = AF_INET; imls->ctx = cf->ctx;