mirror of
https://github.com/nginx/nginx.git
synced 2024-11-23 20:19:02 +08:00
nginx-0.3.46-RELEASE import
*) Feature: the "proxy_hide_header", "proxy_pass_header", "fastcgi_hide_header", and "fastcgi_pass_header" directives. *) Change: the "proxy_pass_x_powered_by", "fastcgi_x_powered_by", and "proxy_pass_server" directives were canceled. *) Feature: the "X-Accel-Buffering" response header line is supported in proxy mode. *) Bugfix: the reconfiguration bug and memory leaks in the ngx_http_perl_module.
This commit is contained in:
parent
418843dc7f
commit
3338cfdfbc
@ -49,5 +49,6 @@ types {
|
||||
video/x-flv flv;
|
||||
video/x-msvideo avi;
|
||||
video/x-ms-wmv wmv;
|
||||
video/x-ms-asf asx asf;
|
||||
video/x-mng mng;
|
||||
}
|
||||
|
@ -9,6 +9,52 @@
|
||||
<title lang="en">nginx changelog</title>
|
||||
|
||||
|
||||
<changes ver="0.3.46" date="11.05.2006">
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
ÄÉÒÅËÔÉ×Ù proxy_hide_header, proxy_pass_header, fastcgi_hide_header
|
||||
É fastcgi_pass_header.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "proxy_hide_header", "proxy_pass_header", "fastcgi_hide_header",
|
||||
and "fastcgi_pass_header" directives.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="change">
|
||||
<para lang="ru">
|
||||
ÄÉÒÅËÔÉ×Ù proxy_x_powered_by, fastcgi_x_powered_by É proxy_pass_server
|
||||
ÕÐÒÁÚÄÎÅÎÙ.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "proxy_pass_x_powered_by", "fastcgi_x_powered_by", and "proxy_pass_server"
|
||||
directives were canceled.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
× ÒÅÖÉÍÅ ÐÒÏËÓÉ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ ÓÔÒÏËÁ ÚÁÇÏÌÏ×ËÁ "X-Accel-Buffering"
|
||||
× ÏÔ×ÅÔÅ ÂÜËÅÎÄÁ.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "X-Accel-Buffering" response header line is supported in proxy mode.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
ÏÛÉÂÏË É ÕÔÅÞÅË ÐÁÍÑÔÉ ÐÒÉ ÐÅÒÅËÏÎÆÉÇÕÒÁÃÉÉ × ÍÏÄÕÌÅ ngx_http_perl_module.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the reconfiguration bug and memory leaks in the ngx_http_perl_module.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
</changes>
|
||||
|
||||
|
||||
<changes ver="0.3.45" date="06.05.2006">
|
||||
|
||||
<change type="feature">
|
||||
@ -777,7 +823,7 @@ only after a successful completion of a request.
|
||||
ÄÉÒÅËÔÉ×Á restrict_host_names ÕÐÒÁÚÄÎÅÎÁ.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "restrict_host_names" directive is canceled.
|
||||
the "restrict_host_names" directive was canceled.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
@ -1057,7 +1103,7 @@ the ngx_http_perl_module supports the $r->args and $r->unescape methods.
|
||||
ÍÅÔÏÄ $r->query_string × ÍÏÄÕÌÅ ngx_http_perl_module ÕÐÒÁÚÄΣÎ.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the method $r->query_string of ngx_http_perl_module is canceled.
|
||||
the method $r->query_string of ngx_http_perl_module was canceled.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
@ -2684,7 +2730,7 @@ Thanks to Alexandr Kukushkin.
|
||||
ÐÅÒÅÎÅÓÅÎÁ ÎÁ ÇÌÏÂÁÌØÎÙÊ ÕÒÏ×ÅÎØ.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "ssl_engine" directive is canceled in the ngx_http_ssl_module
|
||||
the "ssl_engine" directive was canceled in the ngx_http_ssl_module
|
||||
and now is introduced at global level.
|
||||
</para>
|
||||
</change>
|
||||
@ -2934,7 +2980,7 @@ became shorter in the "ps" command.
|
||||
</para>
|
||||
<para lang="en">
|
||||
The changes in the ngx_http_charset_module:
|
||||
the "default_charset" directive is canceled;
|
||||
the "default_charset" directive was canceled;
|
||||
the "charset" directive sets the response charset;
|
||||
the "source_charset" directive sets the source charset only.
|
||||
</para>
|
||||
@ -3673,7 +3719,7 @@ proxy_set_header.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "proxy_set_header" directive.
|
||||
The "proxy_x_var" is canceled and must be replaced with the proxy_set_header
|
||||
The "proxy_x_var" was canceled and must be replaced with the proxy_set_header
|
||||
directive.
|
||||
</para>
|
||||
</change>
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define _NGINX_H_INCLUDED_
|
||||
|
||||
|
||||
#define NGINX_VER "nginx/0.3.45"
|
||||
#define NGINX_VER "nginx/0.3.46"
|
||||
|
||||
#define NGINX_VAR "NGINX"
|
||||
#define NGX_OLDPID_EXT ".oldbin"
|
||||
|
@ -900,38 +900,73 @@ ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
|
||||
|
||||
char *
|
||||
ngx_conf_set_table_elt_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
char *p = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_str_t *value, *s;
|
||||
ngx_array_t **a;
|
||||
ngx_table_elt_t *elt;
|
||||
ngx_conf_post_t *post;
|
||||
|
||||
a = (ngx_array_t **) (p + cmd->offset);
|
||||
|
||||
if (*a == NULL) {
|
||||
*a = ngx_array_create(cf->pool, 4, sizeof(ngx_table_elt_t));
|
||||
*a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
|
||||
if (*a == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
elt = ngx_array_push(*a);
|
||||
if (elt == NULL) {
|
||||
s = ngx_array_push(*a);
|
||||
if (s == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
elt->hash = 0;
|
||||
elt->key = value[1];
|
||||
elt->value = value[2];
|
||||
*s = value[1];
|
||||
|
||||
if (cmd->post) {
|
||||
post = cmd->post;
|
||||
return post->post_handler(cf, post, elt);
|
||||
return post->post_handler(cf, post, s);
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
char *p = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_array_t **a;
|
||||
ngx_keyval_t *kv;
|
||||
ngx_conf_post_t *post;
|
||||
|
||||
a = (ngx_array_t **) (p + cmd->offset);
|
||||
|
||||
if (*a == NULL) {
|
||||
*a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t));
|
||||
if (*a == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
kv = ngx_array_push(*a);
|
||||
if (kv == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
kv->key = value[1];
|
||||
kv->value = value[2];
|
||||
|
||||
if (cmd->post) {
|
||||
post = cmd->post;
|
||||
return post->post_handler(cf, post, kv);
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
@ -323,8 +323,9 @@ void ngx_cdecl ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf,
|
||||
|
||||
char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
char *ngx_conf_set_table_elt_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
char *ngx_conf_set_str_array_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
char *ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
|
@ -524,180 +524,6 @@ ngx_hash_key_lc(u_char *data, size_t len)
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_hash0_init(ngx_hash0_t *hash, ngx_pool_t *pool, void *names,
|
||||
ngx_uint_t nelts)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_str_t *name, *bucket;
|
||||
ngx_uint_t i, n, key, size, best, *test, buckets, min_buckets;
|
||||
|
||||
if (nelts == 0) {
|
||||
for (name = (ngx_str_t *) names;
|
||||
name->len;
|
||||
name = (ngx_str_t *) ((char *) name + hash->bucket_size))
|
||||
{
|
||||
nelts++;
|
||||
}
|
||||
}
|
||||
|
||||
test = ngx_alloc(hash->max_size * sizeof(ngx_uint_t), pool->log);
|
||||
if (test == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
min_buckets = hash->bucket_limit + 1;
|
||||
|
||||
#if (NGX_SUPPRESS_WARN)
|
||||
best = 0;
|
||||
#endif
|
||||
|
||||
for (size = 1; size < hash->max_size; size++) {
|
||||
|
||||
buckets = 0;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
test[i] = 0;
|
||||
}
|
||||
|
||||
for (n = 0, name = (ngx_str_t *) names;
|
||||
n < nelts;
|
||||
n++, name = (ngx_str_t *) ((char *) name + hash->bucket_size))
|
||||
{
|
||||
if (name->data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = 0;
|
||||
|
||||
for (i = 0; i < name->len; i++) {
|
||||
key += ngx_tolower(name->data[i]);
|
||||
}
|
||||
|
||||
key %= size;
|
||||
|
||||
if (test[key] == hash->bucket_limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
test[key]++;
|
||||
|
||||
if (buckets < test[key]) {
|
||||
buckets = test[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (n == nelts) {
|
||||
if (min_buckets > buckets) {
|
||||
min_buckets = buckets;
|
||||
best = size;
|
||||
}
|
||||
|
||||
if (hash->bucket_limit == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (min_buckets == hash->bucket_limit + 1) {
|
||||
ngx_log_error(NGX_LOG_EMERG, pool->log, 0,
|
||||
"could not build the %s hash, you should increase "
|
||||
"either %s_size: %i or %s_bucket_limit: %i",
|
||||
hash->name, hash->name, hash->max_size,
|
||||
hash->name, hash->bucket_limit);
|
||||
ngx_free(test);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
hash->buckets = ngx_pcalloc(pool, best * hash->bucket_size);
|
||||
if (hash->buckets == NULL) {
|
||||
ngx_free(test);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (hash->bucket_limit != 1) {
|
||||
|
||||
for (i = 0; i < best; i++) {
|
||||
test[i] = 0;
|
||||
}
|
||||
|
||||
for (n = 0, name = (ngx_str_t *) names;
|
||||
n < nelts;
|
||||
n++, name = (ngx_str_t *) ((char *) name + hash->bucket_size))
|
||||
{
|
||||
if (name->data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = 0;
|
||||
|
||||
for (i = 0; i < name->len; i++) {
|
||||
key += ngx_tolower(name->data[i]);
|
||||
}
|
||||
|
||||
key %= best;
|
||||
|
||||
test[key]++;
|
||||
}
|
||||
|
||||
for (i = 0; i < best; i++) {
|
||||
if (test[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bucket = ngx_palloc(pool, test[i] * hash->bucket_size);
|
||||
if (bucket == NULL) {
|
||||
ngx_free(test);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
hash->buckets[i] = bucket;
|
||||
bucket->len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = 0, name = (ngx_str_t *) names;
|
||||
n < nelts;
|
||||
n++, name = (ngx_str_t *) ((char *) name + hash->bucket_size))
|
||||
{
|
||||
if (name->data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = 0;
|
||||
|
||||
for (i = 0; i < name->len; i++) {
|
||||
key += ngx_tolower(name->data[i]);
|
||||
}
|
||||
|
||||
key %= best;
|
||||
|
||||
if (hash->bucket_limit == 1) {
|
||||
p = (u_char *) hash->buckets + key * hash->bucket_size;
|
||||
ngx_memcpy(p, name, hash->bucket_size);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (bucket = hash->buckets[key];
|
||||
bucket->len;
|
||||
bucket = (ngx_str_t *) ((char *) bucket + hash->bucket_size))
|
||||
{
|
||||
bucket->len &= 0x7fffffff;
|
||||
}
|
||||
|
||||
ngx_memcpy(bucket, name, hash->bucket_size);
|
||||
bucket->len |= 0x80000000;
|
||||
}
|
||||
|
||||
ngx_free(test);
|
||||
|
||||
hash->hash_size = best;
|
||||
hash->min_buckets = min_buckets;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
|
||||
{
|
||||
|
@ -94,6 +94,7 @@ typedef struct {
|
||||
ngx_uint_t hash;
|
||||
ngx_str_t key;
|
||||
ngx_str_t value;
|
||||
u_char *lowcase_key;
|
||||
} ngx_table_elt_t;
|
||||
|
||||
|
||||
@ -106,7 +107,7 @@ ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
|
||||
ngx_int_t ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
|
||||
ngx_uint_t nelts);
|
||||
|
||||
#define ngx_hash(key, c) key * 31 + c
|
||||
#define ngx_hash(key, c) ((ngx_uint_t) key * 31 + c)
|
||||
ngx_uint_t ngx_hash_key(u_char *data, size_t len);
|
||||
ngx_uint_t ngx_hash_key_lc(u_char *data, size_t len);
|
||||
|
||||
@ -115,9 +116,4 @@ ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key,
|
||||
void *value, ngx_uint_t flags);
|
||||
|
||||
|
||||
#define ngx_hash0(key, c) key + c
|
||||
ngx_int_t ngx_hash0_init(ngx_hash0_t *hash, ngx_pool_t *pool, void *names,
|
||||
ngx_uint_t nelts);
|
||||
|
||||
|
||||
#endif /* _NGX_HASH_H_INCLUDED_ */
|
||||
|
@ -13,11 +13,17 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
u_char *data;
|
||||
size_t len;
|
||||
u_char *data;
|
||||
} ngx_str_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t key;
|
||||
ngx_str_t value;
|
||||
} ngx_keyval_t;
|
||||
|
||||
|
||||
#define ngx_string(str) { sizeof(str) - 1, (u_char *) str }
|
||||
#define ngx_null_string { 0, NULL }
|
||||
|
||||
|
@ -246,13 +246,6 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.redirect_errors),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_x_powered_by"),
|
||||
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_fastcgi_loc_conf_t, upstream.pass_x_powered_by),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_read_timeout"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_msec_slot,
|
||||
@ -318,11 +311,25 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
|
||||
|
||||
{ ngx_string("fastcgi_param"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
|
||||
ngx_conf_set_table_elt_slot,
|
||||
ngx_conf_set_keyval_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_pass_header"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_str_array_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_hide_header"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_str_array_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
@ -358,6 +365,16 @@ ngx_module_t ngx_http_fastcgi_module = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_str_t ngx_http_fastcgi_hide_headers[] = {
|
||||
ngx_string("Status"),
|
||||
ngx_string("X-Accel-Expires"),
|
||||
ngx_string("X-Accel-Redirect"),
|
||||
ngx_string("X-Accel-Limit-Rate"),
|
||||
ngx_string("X-Accel-Buffer"),
|
||||
ngx_null_string
|
||||
};
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_fastcgi_handler(ngx_http_request_t *r)
|
||||
{
|
||||
@ -390,6 +407,8 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
|
||||
u->abort_request = ngx_http_fastcgi_abort_request;
|
||||
u->finalize_request = ngx_http_fastcgi_finalize_request;
|
||||
|
||||
u->buffering = 1;
|
||||
|
||||
u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
|
||||
if (u->pipe == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
@ -796,7 +815,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
|
||||
u_char *start, *last;
|
||||
ngx_str_t *status_line, line;
|
||||
ngx_int_t rc, status;
|
||||
ngx_uint_t key;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_upstream_t *u;
|
||||
ngx_http_fastcgi_ctx_t *f;
|
||||
@ -806,7 +825,6 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
|
||||
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
|
||||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
|
||||
|
||||
if (f == NULL) {
|
||||
f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
|
||||
@ -980,26 +998,34 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
|
||||
h->value.len = r->header_end - r->header_start;
|
||||
|
||||
h->key.data = ngx_palloc(r->pool,
|
||||
h->key.len + 1 + h->value.len + 1);
|
||||
h->key.len + 1 + h->value.len + 1 + h->key.len);
|
||||
if (h->key.data == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
h->value.data = h->key.data + h->key.len + 1;
|
||||
h->lowcase_key = h->key.data + h->key.len + 1
|
||||
+ h->value.len + 1;
|
||||
|
||||
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
|
||||
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
|
||||
|
||||
key = h->hash % umcf->headers_in_hash.hash_size;
|
||||
if (h->key.len == r->lowcase_index) {
|
||||
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
|
||||
|
||||
if (hh[key].name.len == h->key.len
|
||||
&& ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
|
||||
{
|
||||
if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
} else {
|
||||
for (i = 0; i < h->key.len; i++) {
|
||||
h->lowcase_key[i] = ngx_tolower(h->lowcase_key[i]);
|
||||
}
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http fastcgi header: \"%V: %V\"",
|
||||
&h->key, &h->value);
|
||||
@ -1474,9 +1500,11 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* conf->upstream.bufs.num = 0;
|
||||
* conf->upstream.path = NULL;
|
||||
* conf->upstream.next_upstream = 0;
|
||||
* conf->upstream.temp_path = NULL;
|
||||
* conf->upstream.hide_headers_hash = { NULL, 0 };
|
||||
* conf->upstream.hide_headers = NULL;
|
||||
* conf->upstream.pass_headers = NULL;
|
||||
* conf->upstream.schema = { 0, NULL };
|
||||
* conf->upstream.uri = { 0, NULL };
|
||||
* conf->upstream.location = NULL;
|
||||
@ -1510,12 +1538,6 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
|
||||
/* "fastcgi_cyclic_temp_file" is disabled */
|
||||
conf->upstream.cyclic_temp_file = 0;
|
||||
|
||||
conf->upstream.pass_x_powered_by = NGX_CONF_UNSET;
|
||||
|
||||
/* the hardcoded values */
|
||||
conf->upstream.pass_server = 1;
|
||||
conf->upstream.pass_date = 1;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
@ -1529,8 +1551,12 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
u_char *p;
|
||||
size_t size;
|
||||
uintptr_t *code;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *src;
|
||||
ngx_str_t *header;
|
||||
ngx_uint_t i, j;
|
||||
ngx_array_t hide_headers;
|
||||
ngx_keyval_t *src;
|
||||
ngx_hash_key_t *hk;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_script_copy_code_t *copy;
|
||||
|
||||
@ -1682,12 +1708,111 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_conf_merge_value(conf->upstream.redirect_errors,
|
||||
prev->upstream.redirect_errors, 0);
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.pass_x_powered_by,
|
||||
prev->upstream.pass_x_powered_by, 1);
|
||||
|
||||
|
||||
ngx_conf_merge_str_value(conf->index, prev->index, "");
|
||||
|
||||
if (conf->upstream.hide_headers == NULL
|
||||
&& conf->upstream.pass_headers == NULL)
|
||||
{
|
||||
conf->upstream.hide_headers = prev->upstream.hide_headers;
|
||||
conf->upstream.pass_headers = prev->upstream.pass_headers;
|
||||
conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash;
|
||||
|
||||
if (conf->upstream.hide_headers_hash.buckets) {
|
||||
goto peers;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (conf->upstream.hide_headers == NULL) {
|
||||
conf->upstream.hide_headers = prev->upstream.hide_headers;
|
||||
}
|
||||
|
||||
if (conf->upstream.pass_headers == NULL) {
|
||||
conf->upstream.pass_headers = prev->upstream.pass_headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
for (header = ngx_http_fastcgi_hide_headers; header->len; header++) {
|
||||
hk = ngx_array_push(&hide_headers);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
hk->key = *header;
|
||||
hk->key_hash = ngx_hash_key_lc(header->data, header->len);
|
||||
hk->value = (void *) 1;
|
||||
}
|
||||
|
||||
if (conf->upstream.hide_headers) {
|
||||
|
||||
header = conf->upstream.hide_headers->elts;
|
||||
|
||||
for (i = 0; i < conf->upstream.hide_headers->nelts; i++) {
|
||||
|
||||
hk = hide_headers.elts;
|
||||
|
||||
for (j = 0; j < hide_headers.nelts; j++) {
|
||||
if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
|
||||
goto exist;
|
||||
}
|
||||
}
|
||||
|
||||
hk = ngx_array_push(&hide_headers);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
hk->key = header[i];
|
||||
hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len);
|
||||
hk->value = (void *) 1;
|
||||
|
||||
exist:
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->upstream.pass_headers) {
|
||||
|
||||
hk = hide_headers.elts;
|
||||
header = conf->upstream.pass_headers->elts;
|
||||
|
||||
for (i = 0; i < conf->upstream.pass_headers->nelts; i++) {
|
||||
|
||||
for (j = 0; j < hide_headers.nelts; j++) {
|
||||
|
||||
if (hk[j].key.data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
|
||||
hk[j].key.data = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hash.hash = &conf->upstream.hide_headers_hash;
|
||||
hash.key = ngx_hash_key_lc;
|
||||
hash.max_size = 512;
|
||||
hash.bucket_size = ngx_cacheline_size;
|
||||
hash.name = "fastcgi_hide_headers_hash";
|
||||
hash.pool = cf->pool;
|
||||
hash.temp_pool = NULL;
|
||||
|
||||
if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
peers:
|
||||
|
||||
if (conf->peers == NULL) {
|
||||
conf->peers = prev->peers;
|
||||
conf->upstream.schema = prev->upstream.schema;
|
||||
|
@ -524,11 +524,8 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf)
|
||||
conf->upstream.busy_buffers_size = 0;
|
||||
conf->upstream.max_temp_file_size = 0;
|
||||
conf->upstream.temp_file_write_size = 0;
|
||||
conf->upstream.pass_x_powered_by = 0;
|
||||
conf->upstream.redirect_errors = 1;
|
||||
conf->upstream.redirect_404 = 1;
|
||||
conf->upstream.pass_server = 1;
|
||||
conf->upstream.pass_date = 1;
|
||||
conf->upstream.pass_request_headers = 0;
|
||||
conf->upstream.pass_request_body = 0;
|
||||
|
||||
|
@ -42,7 +42,7 @@ typedef struct {
|
||||
ngx_array_t *body_set;
|
||||
ngx_array_t *headers_set_len;
|
||||
ngx_array_t *headers_set;
|
||||
ngx_hash0_t *headers_set_hash;
|
||||
ngx_hash_t headers_set_hash;
|
||||
|
||||
ngx_array_t *headers_source;
|
||||
ngx_array_t *headers_names;
|
||||
@ -187,7 +187,7 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
|
||||
{ ngx_string("proxy_set_header"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
|
||||
ngx_conf_set_table_elt_slot,
|
||||
ngx_conf_set_keyval_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, headers_source),
|
||||
NULL },
|
||||
@ -297,25 +297,18 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.fail_timeout),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_pass_x_powered_by"),
|
||||
{ ngx_string("proxy_pass_header"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
ngx_conf_set_str_array_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_x_powered_by),
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_pass_server"),
|
||||
{ ngx_string("proxy_hide_header"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
ngx_conf_set_str_array_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_server),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_pass_x_accel_expires"),
|
||||
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, upstream.pass_x_accel_expires),
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
@ -356,11 +349,23 @@ ngx_module_t ngx_http_proxy_module = {
|
||||
static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
|
||||
|
||||
|
||||
static ngx_table_elt_t ngx_http_proxy_headers[] = {
|
||||
{ 0, ngx_string("Host"), ngx_string("$proxy_host") },
|
||||
{ 0, ngx_string("Connection"), ngx_string("close") },
|
||||
{ 0, ngx_string("Keep-Alive"), ngx_string("") },
|
||||
{ 0, ngx_null_string, ngx_null_string }
|
||||
static ngx_keyval_t ngx_http_proxy_headers[] = {
|
||||
{ ngx_string("Host"), ngx_string("$proxy_host") },
|
||||
{ ngx_string("Connection"), ngx_string("close") },
|
||||
{ ngx_string("Keep-Alive"), ngx_string("") },
|
||||
{ ngx_null_string, ngx_null_string }
|
||||
};
|
||||
|
||||
|
||||
static ngx_str_t ngx_http_proxy_hide_headers[] = {
|
||||
ngx_string("Date"),
|
||||
ngx_string("Server"),
|
||||
ngx_string("X-Pad"),
|
||||
ngx_string("X-Accel-Expires"),
|
||||
ngx_string("X-Accel-Redirect"),
|
||||
ngx_string("X-Accel-Limit-Rate"),
|
||||
ngx_string("X-Accel-Buffer"),
|
||||
ngx_null_string
|
||||
};
|
||||
|
||||
|
||||
@ -422,16 +427,15 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
|
||||
}
|
||||
|
||||
if (plcf->upstream.buffering) {
|
||||
u->buffering = plcf->upstream.buffering;
|
||||
|
||||
u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
|
||||
if (u->pipe == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
||||
u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
|
||||
if (u->pipe == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
||||
|
||||
u->accel = 1;
|
||||
|
||||
r->upstream = u;
|
||||
@ -450,10 +454,10 @@ static ngx_int_t
|
||||
ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len, loc_len, body_len;
|
||||
ngx_uint_t i, key, unparsed_uri;
|
||||
uintptr_t escape;
|
||||
ngx_buf_t *b;
|
||||
ngx_str_t *hh, method;
|
||||
ngx_str_t method;
|
||||
ngx_uint_t i, unparsed_uri;
|
||||
ngx_chain_t *cl, *body;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *header;
|
||||
@ -541,8 +545,6 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
|
||||
hh = (ngx_str_t *) plcf->headers_set_hash->buckets;
|
||||
|
||||
if (plcf->upstream.pass_request_headers) {
|
||||
part = &r->headers_in.headers.part;
|
||||
header = part->elts;
|
||||
@ -559,10 +561,8 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
key = header[i].hash % plcf->headers_set_hash->hash_size;
|
||||
|
||||
if (hh[key].len == header[i].key.len
|
||||
&& ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
|
||||
if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
|
||||
header[i].lowcase_key, header[i].key.len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -676,10 +676,8 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
key = header[i].hash % plcf->headers_set_hash->hash_size;
|
||||
|
||||
if (hh[key].len == header[i].key.len
|
||||
&& ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
|
||||
if (ngx_hash_find(&plcf->headers_set_hash, header[i].hash,
|
||||
header[i].lowcase_key, header[i].key.len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1055,13 +1053,12 @@ static ngx_int_t
|
||||
ngx_http_proxy_process_header(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t key;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_upstream_header_t *hh;
|
||||
ngx_http_upstream_main_conf_t *umcf;
|
||||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
@ -1082,26 +1079,33 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
||||
h->value.len = r->header_end - r->header_start;
|
||||
|
||||
h->key.data = ngx_palloc(r->pool,
|
||||
h->key.len + 1 + h->value.len + 1);
|
||||
h->key.len + 1 + h->value.len + 1 + h->key.len);
|
||||
if (h->key.data == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
h->value.data = h->key.data + h->key.len + 1;
|
||||
h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
|
||||
|
||||
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
|
||||
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
|
||||
|
||||
key = h->hash % umcf->headers_in_hash.hash_size;
|
||||
if (h->key.len == r->lowcase_index) {
|
||||
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
|
||||
|
||||
if (hh[key].name.len == h->key.len
|
||||
&& ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
|
||||
{
|
||||
if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
} else {
|
||||
for (i = 0; i < h->key.len; i++) {
|
||||
h->lowcase_key[i] = ngx_tolower(h->lowcase_key[i]);
|
||||
}
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http proxy header: \"%V: %V\"",
|
||||
&h->key, &h->value);
|
||||
@ -1116,6 +1120,42 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http proxy header done");
|
||||
|
||||
/*
|
||||
* if no "Server" and "Date" in header line,
|
||||
* then add the special empty headers
|
||||
*/
|
||||
|
||||
if (r->upstream->headers_in.server == NULL) {
|
||||
h = ngx_list_push(&r->upstream->headers_in.headers);
|
||||
if (h == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
|
||||
ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
|
||||
|
||||
h->key.len = sizeof("Server") - 1;
|
||||
h->key.data = (u_char *) "Server";
|
||||
h->value.len = 0;
|
||||
h->value.data = NULL;
|
||||
h->lowcase_key = (u_char *) "server";
|
||||
}
|
||||
|
||||
if (r->upstream->headers_in.date == NULL) {
|
||||
h = ngx_list_push(&r->upstream->headers_in.headers);
|
||||
if (h == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
|
||||
|
||||
h->key.len = sizeof("Date") - 1;
|
||||
h->key.data = (u_char *) "Date";
|
||||
h->value.len = 0;
|
||||
h->value.data = NULL;
|
||||
h->lowcase_key = (u_char *) "date";
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
@ -1406,6 +1446,9 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
||||
* conf->upstream.bufs.num = 0;
|
||||
* conf->upstream.next_upstream = 0;
|
||||
* conf->upstream.temp_path = NULL;
|
||||
* conf->upstream.hide_headers_hash = { NULL, 0 };
|
||||
* conf->upstream.hide_headers = NULL;
|
||||
* conf->upstream.pass_headers = NULL;
|
||||
* conf->upstream.schema = { 0, NULL };
|
||||
* conf->upstream.uri = { 0, NULL };
|
||||
* conf->upstream.location = NULL;
|
||||
@ -1446,12 +1489,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
||||
/* "proxy_cyclic_temp_file" is disabled */
|
||||
conf->upstream.cyclic_temp_file = 0;
|
||||
|
||||
conf->upstream.pass_x_powered_by = NGX_CONF_UNSET;
|
||||
conf->upstream.pass_server = NGX_CONF_UNSET;
|
||||
conf->upstream.pass_date = 0;
|
||||
conf->upstream.pass_x_accel_expires = NGX_CONF_UNSET;
|
||||
|
||||
conf->redirect = NGX_CONF_UNSET;
|
||||
conf->upstream.change_buffering = 1;
|
||||
|
||||
return conf;
|
||||
}
|
||||
@ -1466,9 +1505,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
u_char *p;
|
||||
size_t size;
|
||||
uintptr_t *code;
|
||||
ngx_str_t *name;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *src, *s, *h;
|
||||
ngx_str_t *header;
|
||||
ngx_uint_t i, j;
|
||||
ngx_array_t hide_headers;
|
||||
ngx_keyval_t *src, *s, *h;
|
||||
ngx_hash_key_t *hk;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_http_proxy_redirect_t *pr;
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_script_copy_code_t *copy;
|
||||
@ -1627,14 +1669,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_conf_merge_value(conf->upstream.redirect_errors,
|
||||
prev->upstream.redirect_errors, 0);
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.pass_x_powered_by,
|
||||
prev->upstream.pass_x_powered_by, 1);
|
||||
ngx_conf_merge_value(conf->upstream.pass_server,
|
||||
prev->upstream.pass_server, 0);
|
||||
ngx_conf_merge_value(conf->upstream.pass_x_accel_expires,
|
||||
prev->upstream.pass_x_accel_expires, 0);
|
||||
|
||||
|
||||
ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
|
||||
|
||||
if (conf->redirect) {
|
||||
@ -1662,6 +1696,106 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->upstream.hide_headers == NULL
|
||||
&& conf->upstream.pass_headers == NULL)
|
||||
{
|
||||
conf->upstream.hide_headers = prev->upstream.hide_headers;
|
||||
conf->upstream.pass_headers = prev->upstream.pass_headers;
|
||||
conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash;
|
||||
|
||||
if (conf->upstream.hide_headers_hash.buckets) {
|
||||
goto peers;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (conf->upstream.hide_headers == NULL) {
|
||||
conf->upstream.hide_headers = prev->upstream.hide_headers;
|
||||
}
|
||||
|
||||
if (conf->upstream.pass_headers == NULL) {
|
||||
conf->upstream.pass_headers = prev->upstream.pass_headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
for (header = ngx_http_proxy_hide_headers; header->len; header++) {
|
||||
hk = ngx_array_push(&hide_headers);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
hk->key = *header;
|
||||
hk->key_hash = ngx_hash_key_lc(header->data, header->len);
|
||||
hk->value = (void *) 1;
|
||||
}
|
||||
|
||||
if (conf->upstream.hide_headers) {
|
||||
|
||||
header = conf->upstream.hide_headers->elts;
|
||||
|
||||
for (i = 0; i < conf->upstream.hide_headers->nelts; i++) {
|
||||
|
||||
hk = hide_headers.elts;
|
||||
|
||||
for (j = 0; j < hide_headers.nelts; j++) {
|
||||
if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
|
||||
goto exist;
|
||||
}
|
||||
}
|
||||
|
||||
hk = ngx_array_push(&hide_headers);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
hk->key = header[i];
|
||||
hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len);
|
||||
hk->value = (void *) 1;
|
||||
|
||||
exist:
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->upstream.pass_headers) {
|
||||
|
||||
hk = hide_headers.elts;
|
||||
header = conf->upstream.pass_headers->elts;
|
||||
|
||||
for (i = 0; i < conf->upstream.pass_headers->nelts; i++) {
|
||||
for (j = 0; j < hide_headers.nelts; j++) {
|
||||
|
||||
if (hk[j].key.data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
|
||||
hk[j].key.data = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hash.hash = &conf->upstream.hide_headers_hash;
|
||||
hash.key = ngx_hash_key_lc;
|
||||
hash.max_size = 512;
|
||||
hash.bucket_size = ngx_cacheline_size;
|
||||
hash.name = "proxy_hide_headers_hash";
|
||||
hash.pool = cf->pool;
|
||||
hash.temp_pool = NULL;
|
||||
|
||||
if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
peers:
|
||||
|
||||
if (conf->peers == NULL) {
|
||||
conf->peers = prev->peers;
|
||||
@ -1696,7 +1830,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
if (conf->headers_source == NULL) {
|
||||
conf->headers_source = ngx_array_create(cf->pool, 4,
|
||||
sizeof(ngx_table_elt_t));
|
||||
sizeof(ngx_keyval_t));
|
||||
if (conf->headers_source == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
@ -1707,7 +1841,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
s->hash = 0;
|
||||
s->key.len = sizeof("Content-Length") - 1;
|
||||
s->key.data = (u_char *) "Content-Length";
|
||||
s->value.len = sizeof("$proxy_internal_body_length") - 1;
|
||||
@ -1723,19 +1856,19 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
conf->headers_source = prev->headers_source;
|
||||
}
|
||||
|
||||
if (conf->headers_set_hash) {
|
||||
if (conf->headers_set_hash.buckets) {
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
conf->headers_names = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
|
||||
conf->headers_names = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
|
||||
if (conf->headers_names == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (conf->headers_source == NULL) {
|
||||
conf->headers_source = ngx_array_create(cf->pool, 4,
|
||||
sizeof(ngx_table_elt_t));
|
||||
sizeof(ngx_keyval_t));
|
||||
if (conf->headers_source == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
@ -1780,12 +1913,14 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
src = conf->headers_source->elts;
|
||||
for (i = 0; i < conf->headers_source->nelts; i++) {
|
||||
|
||||
name = ngx_array_push(conf->headers_names);
|
||||
if (name == NULL) {
|
||||
hk = ngx_array_push(conf->headers_names);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
*name = src[i].key;
|
||||
hk->key = src[i].key;
|
||||
hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
|
||||
hk->value = (void *) 1;
|
||||
|
||||
if (src[i].value.len == 0) {
|
||||
continue;
|
||||
@ -1918,6 +2053,23 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
*code = (uintptr_t) NULL;
|
||||
|
||||
|
||||
hash.hash = &conf->headers_set_hash;
|
||||
hash.key = ngx_hash_key_lc;
|
||||
hash.max_size = 512;
|
||||
hash.bucket_size = ngx_cacheline_size;
|
||||
hash.name = "proxy_set_header_hash";
|
||||
hash.pool = cf->pool;
|
||||
hash.temp_pool = NULL;
|
||||
|
||||
if (ngx_hash_init(&hash, conf->headers_names->elts,
|
||||
conf->headers_names->nelts)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash0_t));
|
||||
if (conf->headers_set_hash == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
@ -1940,6 +2092,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
"max buckets per entry: %ui",
|
||||
conf->headers_set_hash->hash_size,
|
||||
conf->headers_set_hash->min_buckets);
|
||||
#endif
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
|
||||
static PerlInterpreter *
|
||||
ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
|
||||
ngx_log_t *log);
|
||||
static ngx_int_t ngx_http_perl_run_requires(ngx_array_t *requires,
|
||||
ngx_log_t *log);
|
||||
static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
|
||||
SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv);
|
||||
static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
|
||||
@ -67,7 +69,10 @@ 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 char *ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post,
|
||||
void *data);
|
||||
#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
|
||||
static void ngx_http_perl_cleanup_perl(void *data);
|
||||
#endif
|
||||
static void ngx_http_perl_cleanup_sv(void *data);
|
||||
|
||||
|
||||
static ngx_conf_post_handler_pt ngx_http_perl_interp_max_p =
|
||||
@ -394,22 +399,6 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
|
||||
|
||||
dTHXa(ctx->perl);
|
||||
|
||||
#if 0
|
||||
|
||||
ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
|
||||
|
||||
if (sv == &PL_sv_undef) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"eval_pv(\"%V\") failed", handler);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (sv == NULL) {
|
||||
sv = newSVpvn((char *) handler->data, handler->len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
sv = newSVpvn((char *) handler->data, handler->len);
|
||||
|
||||
rc = ngx_http_perl_call_handler(aTHX_ r, sv, ¶ms[NGX_HTTP_PERL_SSI_ARG],
|
||||
@ -470,13 +459,18 @@ ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf,
|
||||
static char *
|
||||
ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
|
||||
{
|
||||
ngx_pool_cleanup_t *cln;
|
||||
#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
cln = ngx_pool_cleanup_add(cf->pool, 0);
|
||||
if (cln == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
#else
|
||||
static PerlInterpreter *perl;
|
||||
#endif
|
||||
|
||||
#ifdef NGX_PERL_MODULES
|
||||
if (pmcf->modules.data == NULL) {
|
||||
pmcf->modules.data = NGX_PERL_MODULES;
|
||||
@ -489,6 +483,20 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
|
||||
}
|
||||
}
|
||||
|
||||
#if !(NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
|
||||
|
||||
if (perl) {
|
||||
if (ngx_http_perl_run_requires(&pmcf->requires, cf->log) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
pmcf->perl = perl;
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
PERL_SYS_INIT(&ngx_argc, &ngx_argv);
|
||||
|
||||
pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log);
|
||||
@ -498,9 +506,17 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
|
||||
|
||||
cln->handler = ngx_http_perl_cleanup_perl;
|
||||
cln->data = pmcf->perl;
|
||||
|
||||
#else
|
||||
|
||||
perl = pmcf->perl;
|
||||
|
||||
#endif
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
@ -511,10 +527,6 @@ ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
|
||||
{
|
||||
int n;
|
||||
char *embedding[6];
|
||||
char **script;
|
||||
STRLEN len;
|
||||
ngx_str_t err;
|
||||
ngx_uint_t i;
|
||||
PerlInterpreter *perl;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter");
|
||||
@ -583,22 +595,8 @@ ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
script = pmcf->requires.elts;
|
||||
for (i = 0; i < pmcf->requires.nelts; i++) {
|
||||
require_pv(script[i]);
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
|
||||
err.data = (u_char *) SvPV(ERRSV, len);
|
||||
for (len--; err.data[len] == LF || err.data[len] == CR; len--) {
|
||||
/* void */
|
||||
}
|
||||
err.len = len + 1;
|
||||
|
||||
ngx_log_error(NGX_LOG_EMERG, log, 0,
|
||||
"require_pv(\"%s\") failed: \"%V\"", script[i], &err);
|
||||
goto fail;
|
||||
}
|
||||
if (ngx_http_perl_run_requires(&pmcf->requires, log) != NGX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
}
|
||||
@ -617,6 +615,38 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_perl_run_requires(ngx_array_t *requires, ngx_log_t *log)
|
||||
{
|
||||
char **script;
|
||||
STRLEN len;
|
||||
ngx_str_t err;
|
||||
ngx_uint_t i;
|
||||
|
||||
script = requires->elts;
|
||||
for (i = 0; i < requires->nelts; i++) {
|
||||
|
||||
require_pv(script[i]);
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
|
||||
err.data = (u_char *) SvPV(ERRSV, len);
|
||||
for (len--; err.data[len] == LF || err.data[len] == CR; len--) {
|
||||
/* void */
|
||||
}
|
||||
err.len = len + 1;
|
||||
|
||||
ngx_log_error(NGX_LOG_EMERG, log, 0,
|
||||
"require_pv(\"%s\") failed: \"%V\"", script[i], &err);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (__INTEL_COMPILER)
|
||||
/*
|
||||
* disable 'declaration hides parameter "my_perl"' warning for ENTER and LEAVE
|
||||
@ -740,11 +770,8 @@ ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv)
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_strncmp(p, "sub ", 4) == 0
|
||||
|| ngx_strncmp(p, "use ", 4) == 0)
|
||||
{
|
||||
if (ngx_strncmp(p, "sub ", 4) == 0 || ngx_strncmp(p, "use ", 4) == 0) {
|
||||
*sv = eval_pv((char *) p, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -805,10 +832,12 @@ ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf)
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
|
||||
|
||||
static void
|
||||
ngx_http_perl_cleanup_perl(void *data)
|
||||
{
|
||||
PerlInterpreter *perl = data;
|
||||
PerlInterpreter *perl = data;
|
||||
|
||||
(void) perl_destruct(perl);
|
||||
|
||||
@ -817,6 +846,17 @@ ngx_http_perl_cleanup_perl(void *data)
|
||||
PERL_SYS_TERM();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_perl_cleanup_sv(void *data)
|
||||
{
|
||||
SV *sv = data;
|
||||
|
||||
SvREFCNT_dec(sv);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_perl_preconfiguration(ngx_conf_t *cf)
|
||||
@ -908,6 +948,7 @@ ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_http_perl_loc_conf_t *plcf = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_pool_cleanup_t *cln;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
ngx_http_perl_main_conf_t *pmcf;
|
||||
|
||||
@ -927,6 +968,11 @@ ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
}
|
||||
|
||||
cln = ngx_pool_cleanup_add(cf->pool, 0);
|
||||
if (cln == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
plcf->handler = value[1];
|
||||
|
||||
{
|
||||
@ -947,6 +993,9 @@ ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
|
||||
}
|
||||
|
||||
cln->handler = ngx_http_perl_cleanup_sv;
|
||||
cln->data = plcf->sub;
|
||||
|
||||
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
||||
clcf->handler = ngx_http_perl_handler;
|
||||
|
||||
@ -959,6 +1008,7 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_int_t index;
|
||||
ngx_str_t *value;
|
||||
ngx_pool_cleanup_t *cln;
|
||||
ngx_http_variable_t *v;
|
||||
ngx_http_perl_variable_t *pv;
|
||||
ngx_http_perl_main_conf_t *pmcf;
|
||||
@ -997,6 +1047,11 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
}
|
||||
|
||||
cln = ngx_pool_cleanup_add(cf->pool, 0);
|
||||
if (cln == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
pv->handler = value[2];
|
||||
|
||||
{
|
||||
@ -1017,6 +1072,9 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
|
||||
}
|
||||
|
||||
cln->handler = ngx_http_perl_cleanup_sv;
|
||||
cln->data = pv->sub;
|
||||
|
||||
v->get_handler = ngx_http_perl_variable;
|
||||
v->data = (uintptr_t) pv;
|
||||
|
||||
|
@ -79,11 +79,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_uint_t mi, m, s, l, p, a, i;
|
||||
ngx_uint_t last, bind_all, done;
|
||||
ngx_conf_t pcf;
|
||||
ngx_array_t in_ports;
|
||||
ngx_array_t headers_in, in_ports;
|
||||
ngx_hash_key_t *hk;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_listening_t *ls;
|
||||
ngx_http_listen_t *lscf;
|
||||
ngx_http_module_t *module;
|
||||
ngx_http_header_t *header;
|
||||
ngx_http_in_port_t *hip;
|
||||
ngx_http_handler_pt *h;
|
||||
ngx_http_conf_ctx_t *ctx;
|
||||
@ -373,21 +375,35 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
cmcf->phases[NGX_HTTP_LOG_PHASE].type = NGX_OK;
|
||||
|
||||
|
||||
cmcf->headers_in_hash.max_size = 200;
|
||||
cmcf->headers_in_hash.bucket_limit = 1;
|
||||
cmcf->headers_in_hash.bucket_size = sizeof(ngx_http_header_t);
|
||||
cmcf->headers_in_hash.name = "http headers_in";
|
||||
|
||||
if (ngx_hash0_init(&cmcf->headers_in_hash, cf->pool, ngx_http_headers_in, 0)
|
||||
if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
|
||||
"http headers_in hash size: %ui, max buckets per entry: %ui",
|
||||
cmcf->headers_in_hash.hash_size,
|
||||
cmcf->headers_in_hash.min_buckets);
|
||||
for (header = ngx_http_headers_in; header->name.len; header++) {
|
||||
hk = ngx_array_push(&headers_in);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
hk->key = header->name;
|
||||
hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
|
||||
hk->value = header;
|
||||
}
|
||||
|
||||
hash.hash = &cmcf->headers_in_hash;
|
||||
hash.key = ngx_hash_key_lc;
|
||||
hash.max_size = 512;
|
||||
hash.bucket_size = ngx_cacheline_size;
|
||||
hash.name = "headers_in_hash";
|
||||
hash.pool = cf->pool;
|
||||
hash.temp_pool = NULL;
|
||||
|
||||
if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
for (m = 0; ngx_modules[m]; m++) {
|
||||
if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
|
||||
|
@ -921,42 +921,43 @@ ngx_http_set_content_type(ngx_http_request_t *r)
|
||||
{
|
||||
u_char c, *p, *exten;
|
||||
ngx_str_t *type;
|
||||
ngx_uint_t i;
|
||||
ngx_uint_t i, hash;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
if (r->exten.len) {
|
||||
|
||||
if (!r->low_case_exten) {
|
||||
for (i = 0; i < r->exten.len; i++) {
|
||||
c = r->exten.data[i];
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
hash = 0;
|
||||
|
||||
for (i = 0; i < r->exten.len; i++) {
|
||||
c = r->exten.data[i];
|
||||
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
|
||||
if (i < r->exten.len) {
|
||||
p = ngx_palloc(r->pool, r->exten.len);
|
||||
if (p == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
hash = 0;
|
||||
exten = p;
|
||||
|
||||
for (i = 0; i < r->exten.len; i++) {
|
||||
c = r->exten.data[i];
|
||||
*p++ = ngx_tolower(c);
|
||||
c = ngx_tolower(r->exten.data[i]);
|
||||
hash = ngx_hash(hash, c);
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
r->exten.data = exten;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
r->low_case_exten = 1;
|
||||
hash = ngx_hash(hash, c);
|
||||
}
|
||||
|
||||
type = ngx_hash_find(&clcf->types_hash,
|
||||
ngx_hash_key(r->exten.data, r->exten.len),
|
||||
type = ngx_hash_find(&clcf->types_hash, hash,
|
||||
r->exten.data, r->exten.len);
|
||||
|
||||
if (type) {
|
||||
@ -981,17 +982,9 @@ ngx_http_set_exten(ngx_http_request_t *r)
|
||||
|
||||
for (i = r->uri.len - 1; i > 1; i--) {
|
||||
if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
|
||||
|
||||
r->exten.len = r->uri.len - i - 1;
|
||||
|
||||
if (r->exten.len > 0) {
|
||||
r->exten.data = ngx_palloc(r->pool, r->exten.len + 1);
|
||||
if (r->exten.data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_cpystrn(r->exten.data, &r->uri.data[i + 1],
|
||||
r->exten.len + 1);
|
||||
}
|
||||
r->exten.data = &r->uri.data[i + 1];
|
||||
|
||||
break;
|
||||
|
||||
@ -1000,8 +993,6 @@ ngx_http_set_exten(ngx_http_request_t *r)
|
||||
}
|
||||
}
|
||||
|
||||
r->low_case_exten = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ typedef struct {
|
||||
|
||||
ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1];
|
||||
|
||||
ngx_hash0_t headers_in_hash;
|
||||
ngx_hash_t headers_in_hash;
|
||||
|
||||
ngx_hash_t variables_hash;
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
/* gcc, icc, msvc and others compile these switches as an jump table */
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
{
|
||||
@ -43,8 +45,6 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
for (p = b->pos; p < b->last; p++) {
|
||||
ch = *p;
|
||||
|
||||
/* gcc 2.95.2 and msvc 6.0 compile this switch as an jump table */
|
||||
|
||||
switch (state) {
|
||||
|
||||
/* HTTP methods: GET, HEAD, POST */
|
||||
@ -528,7 +528,7 @@ ngx_int_t
|
||||
ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
{
|
||||
u_char c, ch, *p;
|
||||
ngx_uint_t hash;
|
||||
ngx_uint_t hash, i;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_name,
|
||||
@ -540,8 +540,19 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
sw_header_almost_done
|
||||
} state;
|
||||
|
||||
static u_char lowcase[] =
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0"
|
||||
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
|
||||
"\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
state = r->state;
|
||||
hash = r->header_hash;
|
||||
i = r->lowcase_index;
|
||||
|
||||
for (p = b->pos; p < b->last; p++) {
|
||||
ch = *p;
|
||||
@ -564,14 +575,12 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
state = sw_name;
|
||||
r->header_name_start = p;
|
||||
|
||||
c = (u_char) (ch | 0x20);
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
hash = c;
|
||||
break;
|
||||
}
|
||||
c = lowcase[ch];
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
hash = ch;
|
||||
if (c) {
|
||||
hash = ngx_hash(0, c);
|
||||
r->lowcase_header[0] = c;
|
||||
i = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -584,9 +593,12 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
|
||||
/* header name */
|
||||
case sw_name:
|
||||
c = (u_char) (ch | 0x20);
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
hash += c;
|
||||
c = lowcase[ch];
|
||||
|
||||
if (c) {
|
||||
hash = ngx_hash(hash, c);
|
||||
r->lowcase_header[i++] = c;
|
||||
i &= ~NGX_HTTP_LC_HEADER_LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -596,16 +608,6 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '-') {
|
||||
hash += ch;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
hash += ch;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == CR) {
|
||||
r->header_name_end = p;
|
||||
r->header_start = p;
|
||||
@ -726,6 +728,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
b->pos = p;
|
||||
r->state = state;
|
||||
r->header_hash = hash;
|
||||
r->lowcase_index = i;
|
||||
|
||||
return NGX_AGAIN;
|
||||
|
||||
@ -734,6 +737,7 @@ done:
|
||||
b->pos = p + 1;
|
||||
r->state = sw_start;
|
||||
r->header_hash = hash;
|
||||
r->lowcase_index = i;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
|
@ -25,7 +25,8 @@ static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
|
||||
static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
|
||||
static void ngx_http_find_virtual_server(ngx_http_request_t *r);
|
||||
static void ngx_http_find_virtual_server(ngx_http_request_t *r,
|
||||
ngx_http_virtual_names_t *vn, ngx_uint_t hash);
|
||||
|
||||
static void ngx_http_request_handler(ngx_event_t *ev);
|
||||
static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
|
||||
@ -739,8 +740,8 @@ ngx_http_process_request_headers(ngx_event_t *rev)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_int_t rc, rv;
|
||||
ngx_uint_t key;
|
||||
ngx_str_t header;
|
||||
ngx_uint_t i;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_header_t *hh;
|
||||
@ -763,7 +764,6 @@ ngx_http_process_request_headers(ngx_event_t *rev)
|
||||
|
||||
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
|
||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||
hh = (ngx_http_header_t *) cmcf->headers_in_hash.buckets;
|
||||
|
||||
rc = NGX_AGAIN;
|
||||
|
||||
@ -841,16 +841,28 @@ ngx_http_process_request_headers(ngx_event_t *rev)
|
||||
h->value.data = r->header_start;
|
||||
h->value.data[h->value.len] = '\0';
|
||||
|
||||
key = h->hash % cmcf->headers_in_hash.hash_size;
|
||||
h->lowcase_key = ngx_palloc(r->pool, h->key.len);
|
||||
if (h->lowcase_key == NULL) {
|
||||
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hh[key].name.len == h->key.len
|
||||
&& ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
|
||||
{
|
||||
if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
|
||||
return;
|
||||
if (h->key.len == r->lowcase_index) {
|
||||
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
|
||||
|
||||
} else {
|
||||
for (i = 0; i < h->key.len; i++) {
|
||||
h->lowcase_key[i] = ngx_tolower(h->lowcase_key[i]);
|
||||
}
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
|
||||
h->lowcase_key, h->key.len);
|
||||
|
||||
if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http header: \"%V: %V\"",
|
||||
&h->key, &h->value);
|
||||
@ -1174,12 +1186,16 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len;
|
||||
u_char *ua, *user_agent, ch;
|
||||
ngx_uint_t hash;
|
||||
#if (NGX_HTTP_SSL)
|
||||
long rc;
|
||||
ngx_http_ssl_srv_conf_t *sscf;
|
||||
#endif
|
||||
|
||||
if (r->headers_in.host) {
|
||||
|
||||
hash = 0;
|
||||
|
||||
for (len = 0; len < r->headers_in.host->value.len; len++) {
|
||||
ch = r->headers_in.host->value.data[len];
|
||||
|
||||
@ -1187,16 +1203,21 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
||||
break;
|
||||
}
|
||||
|
||||
r->headers_in.host->value.data[len] = ngx_tolower(ch);
|
||||
ch = ngx_tolower(ch);
|
||||
r->headers_in.host->value.data[len] = ch;
|
||||
hash = ngx_hash(hash, ch);
|
||||
}
|
||||
|
||||
if (r->headers_in.host->value.data[len - 1] == '.') {
|
||||
if (len && r->headers_in.host->value.data[len - 1] == '.') {
|
||||
len--;
|
||||
hash = ngx_hash_key(r->headers_in.host->value.data, len);
|
||||
}
|
||||
|
||||
r->headers_in.host_name_len = len;
|
||||
|
||||
ngx_http_find_virtual_server(r);
|
||||
if (r->virtual_names) {
|
||||
ngx_http_find_virtual_server(r, r->virtual_names, hash);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (r->http_version > NGX_HTTP_VERSION_10) {
|
||||
@ -1345,27 +1366,19 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_find_virtual_server(ngx_http_request_t *r)
|
||||
ngx_http_find_virtual_server(ngx_http_request_t *r,
|
||||
ngx_http_virtual_names_t *vn, ngx_uint_t hash)
|
||||
{
|
||||
size_t len;
|
||||
u_char *host;
|
||||
ngx_http_virtual_names_t *vn;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
ngx_http_core_srv_conf_t *cscf;
|
||||
|
||||
vn = r->virtual_names;
|
||||
|
||||
if (vn == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
host = r->headers_in.host->value.data;
|
||||
len = r->headers_in.host_name_len;
|
||||
|
||||
/* STUB: ngx_hash_key() here is STUB */
|
||||
|
||||
if (vn->hash.buckets) {
|
||||
cscf = ngx_hash_find(&vn->hash, ngx_hash_key(host, len), host, len);
|
||||
cscf = ngx_hash_find(&vn->hash, hash, host, len);
|
||||
if (cscf) {
|
||||
goto found;
|
||||
}
|
||||
|
@ -10,6 +10,9 @@
|
||||
|
||||
#define NGX_HTTP_MAX_REWRITE_CYCLES 10
|
||||
|
||||
/* must be 2^n */
|
||||
#define NGX_HTTP_LC_HEADER_LEN 32
|
||||
|
||||
|
||||
#define NGX_HTTP_DISCARD_BUFFER_SIZE 4096
|
||||
#define NGX_HTTP_LINGERING_BUFFER_SIZE 4096
|
||||
@ -400,7 +403,6 @@ struct ngx_http_request_s {
|
||||
|
||||
unsigned fast_subrequest:1;
|
||||
|
||||
unsigned low_case_exten:1;
|
||||
unsigned header_timeout_set:1;
|
||||
|
||||
unsigned proxy:1;
|
||||
@ -463,7 +465,10 @@ struct ngx_http_request_s {
|
||||
u_char *header_name_end;
|
||||
u_char *header_start;
|
||||
u_char *header_end;
|
||||
|
||||
ngx_uint_t header_hash;
|
||||
ngx_uint_t lowcase_index;
|
||||
u_char lowcase_header[NGX_HTTP_LC_HEADER_LEN];
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,10 +47,9 @@ static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
|
||||
static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_conditional_copy_header_line(ngx_http_request_t *r,
|
||||
static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
|
||||
@ -103,7 +102,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
{ ngx_string("Status"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, status),
|
||||
/* STUB */ ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||
ngx_http_upstream_copy_header_line, 0, 0 },
|
||||
|
||||
{ ngx_string("Content-Type"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
@ -118,14 +117,14 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
{ ngx_string("Date"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, date),
|
||||
ngx_http_upstream_conditional_copy_header_line,
|
||||
offsetof(ngx_http_upstream_conf_t, pass_date), 0 },
|
||||
ngx_http_upstream_copy_header_line,
|
||||
offsetof(ngx_http_headers_out_t, date), 0 },
|
||||
|
||||
{ ngx_string("Server"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, server),
|
||||
ngx_http_upstream_conditional_copy_header_line,
|
||||
offsetof(ngx_http_upstream_conf_t, pass_server), 0 },
|
||||
ngx_http_upstream_copy_header_line,
|
||||
offsetof(ngx_http_headers_out_t, server), 0 },
|
||||
|
||||
{ ngx_string("WWW-Authenticate"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
@ -174,20 +173,14 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
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 },
|
||||
|
||||
{ ngx_string("X-Powered-By"),
|
||||
ngx_http_upstream_ignore_header_line, 0,
|
||||
ngx_http_upstream_conditional_copy_header_line,
|
||||
offsetof(ngx_http_upstream_conf_t, pass_x_powered_by), 0 },
|
||||
ngx_http_upstream_copy_header_line, 0, 0 },
|
||||
|
||||
{ ngx_string("X-Accel-Expires"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, x_accel_expires),
|
||||
ngx_http_upstream_conditional_copy_header_line,
|
||||
offsetof(ngx_http_upstream_conf_t, pass_x_accel_expires), 0 },
|
||||
ngx_http_upstream_copy_header_line, 0, 0 },
|
||||
|
||||
{ ngx_string("X-Accel-Redirect"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
@ -198,6 +191,10 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
ngx_http_upstream_process_limit_rate, 0,
|
||||
ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||
|
||||
{ ngx_string("X-Accel-Buffering"),
|
||||
ngx_http_upstream_process_buffering, 0,
|
||||
ngx_http_upstream_ignore_header_line, 0, 0 },
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
{ ngx_string("Content-Encoding"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
@ -881,7 +878,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t *uri, args;
|
||||
ngx_uint_t i, key, flags;
|
||||
ngx_uint_t i, flags;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_connection_t *c;
|
||||
@ -1089,7 +1086,6 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
|
||||
ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
|
||||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
|
||||
|
||||
part = &r->upstream->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
@ -1106,18 +1102,15 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
key = h[i].hash % umcf->headers_in_hash.hash_size;
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
if (hh[key].redirect
|
||||
&& hh[key].name.len == h[i].key.len
|
||||
&& ngx_strcasecmp(hh[key].name.data, h[i].key.data) == 0)
|
||||
{
|
||||
if (hh[key].copy_handler(r, &h[i], hh[key].conf) != NGX_OK) {
|
||||
if (hh && hh->redirect) {
|
||||
if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1149,7 +1142,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
int tcp_nodelay;
|
||||
ssize_t size;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t i, key;
|
||||
ngx_uint_t i;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_event_pipe_t *p;
|
||||
@ -1161,7 +1154,6 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
ngx_http_upstream_main_conf_t *umcf;
|
||||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
|
||||
|
||||
part = &r->upstream->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
@ -1178,12 +1170,17 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
key = h[i].hash % umcf->headers_in_hash.hash_size;
|
||||
|
||||
if (hh[key].name.len == h[i].key.len
|
||||
&& ngx_strcasecmp(hh[key].name.data, h[i].key.data) == 0)
|
||||
if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len))
|
||||
{
|
||||
if (hh[key].copy_handler(r, &h[i], hh[key].conf) != NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
if (hh) {
|
||||
if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
@ -1199,6 +1196,14 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
}
|
||||
}
|
||||
|
||||
if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
|
||||
r->headers_out.server->hash = 0;
|
||||
}
|
||||
|
||||
if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
|
||||
r->headers_out.date->hash = 0;
|
||||
}
|
||||
|
||||
r->headers_out.status = u->headers_in.status_n;
|
||||
r->headers_out.status_line = u->headers_in.status_line;
|
||||
|
||||
@ -1236,7 +1241,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
if (u->pipe == NULL) {
|
||||
if (!u->buffering) {
|
||||
|
||||
if (u->input_filter == NULL) {
|
||||
u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
|
||||
@ -2053,6 +2058,37 @@ ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
u_char c0, c1, c2;
|
||||
|
||||
if (r->upstream->conf->change_buffering) {
|
||||
|
||||
if (h->value.len == 2) {
|
||||
c0 = ngx_tolower(h->value.data[0]);
|
||||
c1 = ngx_tolower(h->value.data[1]);
|
||||
|
||||
if (c0 == 'n' && c1 == 'o') {
|
||||
r->upstream->buffering = 0;
|
||||
}
|
||||
|
||||
} else if (h->value.len == 3) {
|
||||
c0 = ngx_tolower(h->value.data[0]);
|
||||
c1 = ngx_tolower(h->value.data[1]);
|
||||
c2 = ngx_tolower(h->value.data[2]);
|
||||
|
||||
if (c0 == 'y' && c1 == 'e' && c2 == 's') {
|
||||
r->upstream->buffering = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
@ -2075,30 +2111,6 @@ ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_conditional_copy_header_line(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_flag_t *f;
|
||||
ngx_table_elt_t *ho;
|
||||
|
||||
f = (ngx_flag_t *) ((char *) r->upstream->conf + offset);
|
||||
|
||||
if (*f == 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
if (ho == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ho = *h;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
@ -2554,22 +2566,39 @@ ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
|
||||
{
|
||||
ngx_http_upstream_main_conf_t *umcf = conf;
|
||||
|
||||
umcf->headers_in_hash.max_size = 100;
|
||||
umcf->headers_in_hash.bucket_limit = 1;
|
||||
umcf->headers_in_hash.bucket_size = sizeof(ngx_http_upstream_header_t);
|
||||
umcf->headers_in_hash.name = "upstream_headers_in";
|
||||
ngx_array_t headers_in;
|
||||
ngx_hash_key_t *hk;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_http_upstream_header_t *header;
|
||||
|
||||
if (ngx_hash0_init(&umcf->headers_in_hash, cf->pool,
|
||||
ngx_http_upstream_headers_in, 0) != NGX_OK)
|
||||
if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
|
||||
"http upstream headers_in hash size: %ui, "
|
||||
"max buckets per entry: %ui",
|
||||
umcf->headers_in_hash.hash_size,
|
||||
umcf->headers_in_hash.min_buckets);
|
||||
for (header = ngx_http_upstream_headers_in; header->name.len; header++) {
|
||||
hk = ngx_array_push(&headers_in);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
hk->key = header->name;
|
||||
hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
|
||||
hk->value = header;
|
||||
}
|
||||
|
||||
hash.hash = &umcf->headers_in_hash;
|
||||
hash.key = ngx_hash_key_lc;
|
||||
hash.max_size = 512;
|
||||
hash.bucket_size = ngx_cacheline_size;
|
||||
hash.name = "upstream_headers_in_hash";
|
||||
hash.pool = cf->pool;
|
||||
hash.temp_pool = NULL;
|
||||
|
||||
if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ typedef struct {
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_hash0_t headers_in_hash;
|
||||
ngx_hash_t headers_in_hash;
|
||||
} ngx_http_upstream_main_conf_t;
|
||||
|
||||
|
||||
@ -77,19 +77,19 @@ typedef struct {
|
||||
ngx_flag_t redirect_errors;
|
||||
ngx_flag_t cyclic_temp_file;
|
||||
|
||||
ngx_flag_t pass_x_powered_by;
|
||||
ngx_flag_t pass_server;
|
||||
ngx_flag_t pass_date;
|
||||
ngx_flag_t pass_x_accel_expires;
|
||||
|
||||
ngx_path_t *temp_path;
|
||||
|
||||
ngx_hash_t hide_headers_hash;
|
||||
ngx_array_t *hide_headers;
|
||||
ngx_array_t *pass_headers;
|
||||
|
||||
ngx_str_t schema;
|
||||
ngx_str_t uri;
|
||||
ngx_str_t location;
|
||||
ngx_str_t url; /* used in proxy_rewrite_location */
|
||||
|
||||
ngx_uint_t redirect_404; /* unsigned redirect_404:1; */
|
||||
unsigned redirect_404:1;
|
||||
unsigned change_buffering:1;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
ngx_ssl_t *ssl;
|
||||
@ -191,6 +191,8 @@ struct ngx_http_upstream_s {
|
||||
unsigned cachable:1;
|
||||
unsigned accel:1;
|
||||
|
||||
unsigned buffering:1;
|
||||
|
||||
unsigned request_sent:1;
|
||||
unsigned header_sent:1;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user