Mercurial > hg > nginx-quic
comparison src/http/ngx_http_variables.c @ 509:9b8c906f6e63 release-0.1.29
nginx-0.1.29-RELEASE import
*) Feature: the ngx_http_ssi_module supports "include virtual" command.
*) Feature: the ngx_http_ssi_module supports the condition command like
'if expr="$NAME"' and "else" and "endif" commands. Only one nested
level is supported.
*) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and
DATE_GMT variables and "config timefmt" command.
*) Feature: the "ssi_ignore_recycled_buffers" directive.
*) Bugfix: the "echo" command did not show the default value for the
empty QUERY_STRING variable.
*) Change: the ngx_http_proxy_module was rewritten.
*) Feature: the "proxy_redirect", "proxy_pass_request_headers",
"proxy_pass_request_body", and "proxy_method" directives.
*) Feature: the "proxy_set_header" directive. The "proxy_x_var" was
canceled and must be replaced with the proxy_set_header directive.
*) Change: the "proxy_preserve_host" is canceled and must be replaced
with the "proxy_set_header Host $host" and the "proxy_redirect off"
directives, the "proxy_set_header Host $host:$proxy_port" directive
and the appropriate proxy_redirect directives.
*) Change: the "proxy_set_x_real_ip" is canceled and must be replaced
with the "proxy_set_header X-Real-IP $remote_addr" directive.
*) Change: the "proxy_add_x_forwarded_for" is canceled and must be
replaced with
the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for"
directive.
*) Change: the "proxy_set_x_url" is canceled and must be replaced with
the "proxy_set_header X-URL http://$host:$server_port$request_uri"
directive.
*) Feature: the "fastcgi_param" directive.
*) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params"
directive are canceled and must be replaced with the fastcgi_param
directives.
*) Feature: the "index" directive can use the variables.
*) Feature: the "index" directive can be used at http and server levels.
*) Change: the last index only in the "index" directive can be absolute.
*) Feature: the "rewrite" directive can use the variables.
*) Feature: the "internal" directive.
*) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR,
SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME,
REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables.
*) Change: nginx now passes the invalid lines in a client request
headers or a backend response header.
*) Bugfix: if the backend did not transfer response for a long time and
the "send_timeout" was less than "proxy_read_timeout", then nginx
returned the 408 response.
*) Bugfix: the segmentation fault was occurred if the backend sent an
invalid line in response header; the bug had appeared in 0.1.26.
*) Bugfix: the segmentation fault may occurred in FastCGI fault
tolerance configuration.
*) Bugfix: the "expires" directive did not remove the previous
"Expires" and "Cache-Control" headers.
*) Bugfix: nginx did not take into account trailing dot in "Host"
header line.
*) Bugfix: the ngx_http_auth_module did not work under Linux.
*) Bugfix: the rewrite directive worked incorrectly, if the arguments
were in a request.
*) Bugfix: nginx could not be built on MacOS X.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 12 May 2005 14:58:06 +0000 |
parents | d4ea69372b94 |
children | 417a087c9c4d |
comparison
equal
deleted
inserted
replaced
508:ca1020ce99ba | 509:9b8c906f6e63 |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_event.h> | 9 #include <ngx_event.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | 11 |
12 | 12 |
13 #define NGX_HTTP_VARS_HASH_PRIME 29 | 13 static ngx_http_variable_value_t * |
14 | 14 ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data); |
15 #define ngx_http_vars_hash_key(key, vn) \ | |
16 { \ | |
17 ngx_uint_t n; \ | |
18 for (key = 0, n = 0; n < (vn)->len; n++) { \ | |
19 key += (vn)->data[n]; \ | |
20 } \ | |
21 key %= NGX_HTTP_VARS_HASH_PRIME; \ | |
22 } | |
23 | |
24 | |
25 static ngx_http_variable_value_t * | 15 static ngx_http_variable_value_t * |
26 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data); | 16 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data); |
27 static ngx_http_variable_value_t * | 17 static ngx_http_variable_value_t * |
28 ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data); | 18 ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data); |
29 static ngx_http_variable_value_t * | 19 static ngx_http_variable_value_t * |
20 ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data); | |
21 static ngx_http_variable_value_t * | |
30 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data); | 22 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data); |
31 static ngx_http_variable_value_t * | 23 static ngx_http_variable_value_t * |
32 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data); | 24 ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data); |
33 static ngx_http_variable_value_t * | 25 static ngx_http_variable_value_t * |
34 ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data); | 26 ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data); |
35 | 27 static ngx_http_variable_value_t * |
36 | 28 ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data); |
37 static ngx_array_t *ngx_http_core_variables_hash; | 29 static ngx_http_variable_value_t * |
38 | 30 ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data); |
39 | 31 static ngx_http_variable_value_t * |
40 static ngx_http_core_variable_t ngx_http_core_variables[] = { | 32 ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data); |
41 | 33 |
42 { ngx_string("HTTP_HOST"), ngx_http_variable_header, | 34 |
43 offsetof(ngx_http_headers_in_t, host) }, | 35 /* |
44 | 36 * TODO: |
45 { ngx_string("HTTP_USER_AGENT"), ngx_http_variable_header, | 37 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED |
46 offsetof(ngx_http_headers_in_t, user_agent) }, | 38 * REMOTE_HOST (null), REMOTE_IDENT (null), |
47 | 39 * SERVER_SOFTWARE |
48 { ngx_string("HTTP_REFERER"), ngx_http_variable_header, | 40 * |
49 offsetof(ngx_http_headers_in_t, referer) }, | 41 * Apache SSI: DATE_GMT, DOCUMENT_NAME, LAST_MODIFIED, |
42 * USER_NAME (file owner) | |
43 */ | |
44 | |
45 static ngx_http_variable_t ngx_http_core_variables[] = { | |
46 | |
47 { ngx_string("http_host"), ngx_http_variable_header, | |
48 offsetof(ngx_http_request_t, headers_in.host), 0 }, | |
49 | |
50 { ngx_string("http_user_agent"), ngx_http_variable_header, | |
51 offsetof(ngx_http_request_t, headers_in.user_agent), 0 }, | |
52 | |
53 { ngx_string("http_referer"), ngx_http_variable_header, | |
54 offsetof(ngx_http_request_t, headers_in.referer), 0 }, | |
50 | 55 |
51 #if (NGX_HTTP_GZIP) | 56 #if (NGX_HTTP_GZIP) |
52 { ngx_string("HTTP_VIA"), ngx_http_variable_header, | 57 { ngx_string("http_via"), ngx_http_variable_header, |
53 offsetof(ngx_http_headers_in_t, via) }, | 58 offsetof(ngx_http_request_t, headers_in.via), 0 }, |
54 #endif | 59 #endif |
55 | 60 |
56 #if (NGX_HTTP_PROXY) | 61 #if (NGX_HTTP_PROXY) |
57 { ngx_string("HTTP_X_FORWARDED_FOR"), ngx_http_variable_header, | 62 { ngx_string("http_x_forwarded_for"), ngx_http_variable_header, |
58 offsetof(ngx_http_headers_in_t, x_forwarded_for) }, | 63 offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0 }, |
59 #endif | 64 #endif |
60 | 65 |
61 { ngx_string("REMOTE_ADDR"), ngx_http_variable_remote_addr, 0 }, | 66 { ngx_string("content_length"), ngx_http_variable_header, |
62 | 67 offsetof(ngx_http_request_t, headers_in.content_length), 0 }, |
63 { ngx_string("DOCUMENT_URI"), ngx_http_variable_uri, 0 }, | 68 |
64 | 69 { ngx_string("content_type"), ngx_http_variable_header, |
65 { ngx_string("QUERY_STRING"), ngx_http_variable_query_string, 0 }, | 70 offsetof(ngx_http_request_t, headers_in.content_type), 0 }, |
66 | 71 |
67 { ngx_null_string, NULL, 0 } | 72 { ngx_string("host"), ngx_http_variable_host, 0, 0 }, |
73 | |
74 { ngx_string("remote_addr"), ngx_http_variable_remote_addr, 0, 0 }, | |
75 | |
76 { ngx_string("remote_port"), ngx_http_variable_remote_port, 0, 0 }, | |
77 | |
78 { ngx_string("server_addr"), ngx_http_variable_server_addr, 0, 0 }, | |
79 | |
80 { ngx_string("server_port"), ngx_http_variable_server_port, 0, 0 }, | |
81 | |
82 { ngx_string("server_protocol"), ngx_http_variable_request, | |
83 offsetof(ngx_http_request_t, http_protocol), 0 }, | |
84 | |
85 { ngx_string("request_uri"), ngx_http_variable_request, | |
86 offsetof(ngx_http_request_t, unparsed_uri), 0 }, | |
87 | |
88 { ngx_string("document_uri"), ngx_http_variable_request, | |
89 offsetof(ngx_http_request_t, uri), 0 }, | |
90 | |
91 { ngx_string("document_root"), ngx_http_variable_document_root, 0, 0 }, | |
92 | |
93 { ngx_string("query_string"), ngx_http_variable_request, | |
94 offsetof(ngx_http_request_t, args), | |
95 NGX_HTTP_VAR_NOCACHABLE }, | |
96 | |
97 { ngx_string("request_filename"), ngx_http_variable_request_filename, 0, | |
98 NGX_HTTP_VAR_NOCACHABLE }, | |
99 | |
100 { ngx_string("server_name"), ngx_http_variable_request, | |
101 offsetof(ngx_http_request_t, server_name), 0 }, | |
102 | |
103 { ngx_string("request_method"), ngx_http_variable_request, | |
104 offsetof(ngx_http_request_t, method_name), 0 }, | |
105 | |
106 { ngx_string("remote_user"), ngx_http_variable_request, | |
107 offsetof(ngx_http_request_t, headers_in.user), 0 }, | |
108 | |
109 { ngx_null_string, NULL, 0, 0 } | |
68 }; | 110 }; |
69 | 111 |
70 | 112 |
71 ngx_http_variable_t * | 113 ngx_http_variable_t * |
72 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set) | 114 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) |
115 { | |
116 ngx_uint_t i; | |
117 ngx_http_variable_t *v; | |
118 ngx_http_core_main_conf_t *cmcf; | |
119 | |
120 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
121 | |
122 v = cmcf->all_variables.elts; | |
123 for (i = 0; i < cmcf->all_variables.nelts; i++) { | |
124 if (name->len != v[i].name.len | |
125 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) | |
126 { | |
127 continue; | |
128 } | |
129 | |
130 if (!(v[i].flags & NGX_HTTP_VAR_CHANGABLE)) { | |
131 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
132 "the duplicate \"%V\" variable", name); | |
133 return NULL; | |
134 } | |
135 | |
136 return &v[i]; | |
137 } | |
138 | |
139 v = ngx_array_push(&cmcf->all_variables); | |
140 if (v == NULL) { | |
141 return NULL; | |
142 } | |
143 | |
144 v->name.len = name->len; | |
145 v->name.data = ngx_palloc(cf->pool, name->len); | |
146 if (v->name.data == NULL) { | |
147 return NULL; | |
148 } | |
149 | |
150 for (i = 0; i < name->len; i++) { | |
151 v->name.data[i] = ngx_tolower(name->data[i]); | |
152 } | |
153 | |
154 v->handler = NULL; | |
155 v->data = 0; | |
156 v->flags = flags; | |
157 | |
158 return v; | |
159 } | |
160 | |
161 | |
162 ngx_int_t | |
163 ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) | |
73 { | 164 { |
74 ngx_uint_t i; | 165 ngx_uint_t i; |
75 ngx_http_variable_t *v; | 166 ngx_http_variable_t *v; |
76 ngx_http_core_main_conf_t *cmcf; | 167 ngx_http_core_main_conf_t *cmcf; |
77 | 168 |
81 | 172 |
82 if (v == NULL) { | 173 if (v == NULL) { |
83 if (ngx_array_init(&cmcf->variables, cf->pool, 4, | 174 if (ngx_array_init(&cmcf->variables, cf->pool, 4, |
84 sizeof(ngx_http_variable_t)) == NGX_ERROR) | 175 sizeof(ngx_http_variable_t)) == NGX_ERROR) |
85 { | 176 { |
86 return NULL; | 177 return NGX_ERROR; |
87 } | 178 } |
88 | 179 |
89 } else { | 180 } else { |
90 for (i = 0; i < cmcf->variables.nelts; i++) { | 181 for (i = 0; i < cmcf->variables.nelts; i++) { |
91 if (name->len != v[i].name.len | 182 if (name->len != v[i].name.len |
92 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) | 183 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) |
93 { | 184 { |
94 continue; | 185 continue; |
95 } | 186 } |
96 | 187 |
97 if (set && v[i].handler) { | 188 return i; |
98 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
99 "the duplicate \"%V\" variable", name); | |
100 return NULL; | |
101 } | |
102 | |
103 return &v[i]; | |
104 } | 189 } |
105 } | 190 } |
106 | 191 |
107 v = ngx_array_push(&cmcf->variables); | 192 v = ngx_array_push(&cmcf->variables); |
108 if (v == NULL) { | 193 if (v == NULL) { |
109 return NULL; | 194 return NGX_ERROR; |
110 } | 195 } |
111 | 196 |
112 v->name.len = name->len; | 197 v->name.len = name->len; |
113 v->name.data = ngx_palloc(cf->pool, name->len); | 198 v->name.data = ngx_palloc(cf->pool, name->len); |
114 if (v->name.data == NULL) { | 199 if (v->name.data == NULL) { |
115 return NULL; | 200 return NGX_ERROR; |
116 } | 201 } |
117 | 202 |
118 for (i = 0; i < name->len; i++) { | 203 for (i = 0; i < name->len; i++) { |
119 v->name.data[i] = ngx_toupper(name->data[i]); | 204 v->name.data[i] = ngx_tolower(name->data[i]); |
120 } | 205 } |
121 | 206 |
122 v->index = cmcf->variables.nelts - 1; | |
123 v->handler = NULL; | 207 v->handler = NULL; |
124 v->data = 0; | 208 v->data = 0; |
125 | 209 v->flags = 0; |
126 return v; | 210 |
211 return cmcf->variables.nelts - 1; | |
127 } | 212 } |
128 | 213 |
129 | 214 |
130 ngx_http_variable_value_t * | 215 ngx_http_variable_value_t * |
131 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) | 216 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) |
156 if (r->variables == NULL) { | 241 if (r->variables == NULL) { |
157 return NULL; | 242 return NULL; |
158 } | 243 } |
159 } | 244 } |
160 | 245 |
161 r->variables[index] = vv; | 246 if (!(v[index].flags & NGX_HTTP_VAR_NOCACHABLE)) { |
247 r->variables[index] = vv; | |
248 } | |
162 | 249 |
163 return vv; | 250 return vv; |
164 } | 251 } |
165 | 252 |
166 | 253 |
167 ngx_http_variable_value_t * | 254 ngx_http_variable_value_t * |
168 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) | 255 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) |
169 { | 256 { |
170 ngx_uint_t i, key; | 257 ngx_uint_t i, key; |
171 ngx_http_variable_t *v; | 258 ngx_http_variable_t *v; |
172 ngx_http_core_variable_t *cv; | |
173 ngx_http_core_main_conf_t *cmcf; | 259 ngx_http_core_main_conf_t *cmcf; |
174 | 260 |
175 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | 261 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
176 | 262 |
177 v = cmcf->variables.elts; | 263 key = 0; |
178 for (i = 0; i < cmcf->variables.nelts; i++) { | 264 for (i = 0; i < name->len; i++) { |
179 if (v[i].name.len != name->len) { | 265 key += name->data[i]; |
180 continue; | 266 } |
181 } | 267 |
182 | 268 key %= cmcf->variables_hash.hash_size; |
183 if (ngx_strncmp(v[i].name.data, name->data, name->len) == 0) { | 269 v = (ngx_http_variable_t *) cmcf->variables_hash.buckets; |
184 return ngx_http_get_indexed_variable(r, v[i].index); | 270 |
185 } | 271 if (v[key].name.len == name->len |
186 } | 272 && ngx_strncmp(v[key].name.data, name->data, name->len) == 0) |
187 | 273 { |
188 ngx_http_vars_hash_key(key, name); | 274 return v[key].handler(r, v[key].data); |
189 | 275 } |
190 cv = ngx_http_core_variables_hash[key].elts; | 276 |
191 for (i = 0; i < ngx_http_core_variables_hash[key].nelts; i++) { | 277 if (ngx_strncmp(name->data, "http_", 5) == 0) { |
192 if (cv[i].name.len != name->len) { | |
193 continue; | |
194 } | |
195 | |
196 if (ngx_strncmp(cv[i].name.data, name->data, name->len) == 0) { | |
197 return cv[i].handler(r, cv[i].data); | |
198 } | |
199 } | |
200 | |
201 if (ngx_strncmp(name->data, "HTTP_", 5) == 0) { | |
202 return ngx_http_variable_unknown_header(r, (uintptr_t) name); | 278 return ngx_http_variable_unknown_header(r, (uintptr_t) name); |
203 } | 279 } |
204 | 280 |
205 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 281 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
206 "unknown \"%V\" variable", name); | 282 "unknown \"%V\" variable", name); |
207 | 283 |
208 return NGX_HTTP_VARIABLE_NOT_FOUND; | 284 return NGX_HTTP_VAR_NOT_FOUND; |
285 } | |
286 | |
287 | |
288 static ngx_http_variable_value_t * | |
289 ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data) | |
290 { | |
291 ngx_str_t *s; | |
292 ngx_http_variable_value_t *vv; | |
293 | |
294 s = (ngx_str_t *) ((char *) r + data); | |
295 | |
296 if (s->data == NULL) { | |
297 return NGX_HTTP_VAR_NOT_FOUND; | |
298 } | |
299 | |
300 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
301 if (vv == NULL) { | |
302 return NULL; | |
303 } | |
304 | |
305 vv->value = 0; | |
306 vv->text = *s; | |
307 | |
308 return vv; | |
209 } | 309 } |
210 | 310 |
211 | 311 |
212 static ngx_http_variable_value_t * | 312 static ngx_http_variable_value_t * |
213 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data) | 313 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data) |
214 { | 314 { |
215 ngx_table_elt_t *h; | 315 ngx_table_elt_t *h; |
216 ngx_http_variable_value_t *vv; | 316 ngx_http_variable_value_t *vv; |
217 | 317 |
218 h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data); | 318 h = *(ngx_table_elt_t **) ((char *) r + data); |
219 | 319 |
220 if (h == NULL) { | 320 if (h == NULL) { |
221 return NGX_HTTP_VARIABLE_NOT_FOUND; | 321 return NGX_HTTP_VAR_NOT_FOUND; |
222 } | 322 } |
223 | 323 |
224 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | 324 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); |
225 if (vv == NULL) { | 325 if (vv == NULL) { |
226 return NULL; | 326 return NULL; |
257 part = part->next; | 357 part = part->next; |
258 header = part->elts; | 358 header = part->elts; |
259 i = 0; | 359 i = 0; |
260 } | 360 } |
261 | 361 |
262 for (n = 0; n + 5 < var->len && n < header[i].key.len; n++) | 362 for (n = 0; n + 5 < var->len && n < header[i].key.len; n++) { |
263 { | |
264 ch = header[i].key.data[n]; | 363 ch = header[i].key.data[n]; |
265 | 364 |
266 if (ch >= 'a' && ch <= 'z') { | 365 if (ch >= 'A' && ch <= 'Z') { |
267 ch &= ~0x20; | 366 ch |= 0x20; |
268 | 367 |
269 } else if (ch == '-') { | 368 } else if (ch == '-') { |
270 ch = '_'; | 369 ch = '_'; |
271 } | 370 } |
272 | 371 |
285 vv->text = header[i].value; | 384 vv->text = header[i].value; |
286 return vv; | 385 return vv; |
287 } | 386 } |
288 } | 387 } |
289 | 388 |
290 return NGX_HTTP_VARIABLE_NOT_FOUND; | 389 return NGX_HTTP_VAR_NOT_FOUND; |
390 } | |
391 | |
392 | |
393 static ngx_http_variable_value_t * | |
394 ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data) | |
395 { | |
396 ngx_http_variable_value_t *vv; | |
397 | |
398 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
399 if (vv == NULL) { | |
400 return NULL; | |
401 } | |
402 | |
403 vv->value = 0; | |
404 | |
405 if (r->headers_in.host) { | |
406 vv->text.len = r->headers_in.host_name_len; | |
407 vv->text.data = r->headers_in.host->value.data; | |
408 | |
409 } else { | |
410 vv->text = r->server_name; | |
411 } | |
412 | |
413 return vv; | |
291 } | 414 } |
292 | 415 |
293 | 416 |
294 static ngx_http_variable_value_t * | 417 static ngx_http_variable_value_t * |
295 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data) | 418 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data) |
307 return vv; | 430 return vv; |
308 } | 431 } |
309 | 432 |
310 | 433 |
311 static ngx_http_variable_value_t * | 434 static ngx_http_variable_value_t * |
312 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data) | 435 ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data) |
313 { | 436 { |
314 ngx_http_variable_value_t *vv; | 437 ngx_uint_t port; |
315 | 438 struct sockaddr_in *sin; |
316 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | 439 ngx_http_variable_value_t *vv; |
317 if (vv == NULL) { | 440 |
318 return NULL; | 441 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); |
319 } | 442 if (vv == NULL) { |
320 | 443 return NULL; |
321 vv->value = 0; | 444 } |
322 vv->text = r->uri; | 445 |
323 | 446 vv->value = 0; |
324 return vv; | 447 vv->text.len = 0; |
325 } | 448 |
326 | 449 vv->text.data = ngx_palloc(r->pool, sizeof("65535") - 1); |
327 | 450 if (vv->text.data == NULL) { |
328 static ngx_http_variable_value_t * | 451 return NULL; |
329 ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data) | 452 } |
330 { | 453 |
331 ngx_http_variable_value_t *vv; | 454 /* AF_INET only */ |
332 | 455 |
333 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | 456 if (r->connection->sockaddr->sa_family == AF_INET) { |
334 if (vv == NULL) { | 457 sin = (struct sockaddr_in *) r->connection->sockaddr; |
335 return NULL; | 458 |
336 } | 459 port = ntohs(sin->sin_port); |
337 | 460 |
338 vv->value = 0; | 461 if (port > 0 && port < 65536) { |
339 vv->text = r->args; | 462 vv->value = port; |
463 vv->text.len = ngx_sprintf(vv->text.data, "%ui", port) | |
464 - vv->text.data; | |
465 } | |
466 } | |
467 | |
468 return vv; | |
469 } | |
470 | |
471 | |
472 static ngx_http_variable_value_t * | |
473 ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data) | |
474 { | |
475 socklen_t len; | |
476 ngx_connection_t *c; | |
477 struct sockaddr_in sin; | |
478 ngx_http_variable_value_t *vv; | |
479 | |
480 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
481 if (vv == NULL) { | |
482 return NULL; | |
483 } | |
484 | |
485 vv->value = 0; | |
486 | |
487 vv->text.data = ngx_palloc(r->pool, INET_ADDRSTRLEN); | |
488 if (vv->text.data == NULL) { | |
489 return NULL; | |
490 } | |
491 | |
492 c = r->connection; | |
493 | |
494 if (r->in_addr == 0) { | |
495 len = sizeof(struct sockaddr_in); | |
496 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { | |
497 ngx_log_error(NGX_LOG_CRIT, c->log, | |
498 ngx_socket_errno, "getsockname() failed"); | |
499 return NULL; | |
500 } | |
501 | |
502 r->in_addr = sin.sin_addr.s_addr; | |
503 } | |
504 | |
505 vv->text.len = ngx_inet_ntop(c->listening->family, &r->in_addr, | |
506 vv->text.data, INET_ADDRSTRLEN); | |
507 | |
508 return vv; | |
509 } | |
510 | |
511 | |
512 static ngx_http_variable_value_t * | |
513 ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data) | |
514 { | |
515 ngx_http_variable_value_t *vv; | |
516 | |
517 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
518 if (vv == NULL) { | |
519 return NULL; | |
520 } | |
521 | |
522 vv->value = r->port; | |
523 vv->text.len = r->port_text->len - 1; | |
524 vv->text.data = r->port_text->data + 1; | |
525 | |
526 return vv; | |
527 } | |
528 | |
529 | |
530 static ngx_http_variable_value_t * | |
531 ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data) | |
532 { | |
533 ngx_http_core_loc_conf_t *clcf; | |
534 ngx_http_variable_value_t *vv; | |
535 | |
536 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
537 if (vv == NULL) { | |
538 return NULL; | |
539 } | |
540 | |
541 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
542 | |
543 vv->value = 0; | |
544 vv->text = clcf->root; | |
545 | |
546 return vv; | |
547 } | |
548 | |
549 | |
550 static ngx_http_variable_value_t * | |
551 ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data) | |
552 { | |
553 u_char *p; | |
554 ngx_http_core_loc_conf_t *clcf; | |
555 ngx_http_variable_value_t *vv; | |
556 | |
557 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
558 if (vv == NULL) { | |
559 return NULL; | |
560 } | |
561 | |
562 vv->value = 0; | |
563 | |
564 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
565 | |
566 if (!clcf->alias) { | |
567 vv->text.len = clcf->root.len + r->uri.len; | |
568 vv->text.data = ngx_palloc(r->pool, vv->text.len); | |
569 if (vv->text.data == NULL) { | |
570 return NULL; | |
571 } | |
572 | |
573 p = ngx_cpymem(vv->text.data, clcf->root.data, clcf->root.len); | |
574 ngx_memcpy(p, r->uri.data, r->uri.len + 1); | |
575 | |
576 } else { | |
577 vv->text.len = clcf->root.len + r->uri.len + 2 - clcf->name.len; | |
578 vv->text.data = ngx_palloc(r->pool, vv->text.len); | |
579 if (vv->text.data == NULL) { | |
580 return NULL; | |
581 } | |
582 | |
583 p = ngx_cpymem(vv->text.data, clcf->root.data, clcf->root.len); | |
584 ngx_memcpy(p, r->uri.data + clcf->name.len, | |
585 r->uri.len + 1 - clcf->name.len); | |
586 } | |
340 | 587 |
341 return vv; | 588 return vv; |
342 } | 589 } |
343 | 590 |
344 | 591 |
345 ngx_int_t | 592 ngx_int_t |
346 ngx_http_variables_init(ngx_cycle_t *cycle) | 593 ngx_http_variables_add_core_vars(ngx_conf_t *cf) |
347 { | 594 { |
348 ngx_uint_t i, j, key; | 595 ngx_http_variable_t *v, *cv; |
349 ngx_http_variable_t *v; | |
350 ngx_http_core_variable_t *cv, *vp; | |
351 ngx_http_core_main_conf_t *cmcf; | 596 ngx_http_core_main_conf_t *cmcf; |
352 | 597 |
353 ngx_http_core_variables_hash = ngx_palloc(cycle->pool, | 598 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
354 NGX_HTTP_VARS_HASH_PRIME | 599 |
355 * sizeof(ngx_array_t)); | 600 if (ngx_array_init(&cmcf->all_variables, cf->pool, 32, |
356 if (ngx_http_core_variables_hash == NULL) { | 601 sizeof(ngx_http_variable_t)) == NGX_ERROR) |
602 { | |
357 return NGX_ERROR; | 603 return NGX_ERROR; |
358 } | 604 } |
359 | 605 |
360 for (i = 0; i < NGX_HTTP_VARS_HASH_PRIME; i++) { | 606 for (cv = ngx_http_core_variables; cv->name.len; cv++) { |
361 if (ngx_array_init(&ngx_http_core_variables_hash[i], cycle->pool, 4, | 607 v = ngx_array_push(&cmcf->all_variables); |
362 sizeof(ngx_http_core_variable_t)) == NGX_ERROR) | 608 if (v == NULL) { |
363 { | |
364 return NGX_ERROR; | 609 return NGX_ERROR; |
365 } | 610 } |
366 } | 611 |
367 | 612 *v = *cv; |
368 for (cv = ngx_http_core_variables; cv->name.len; cv++) { | 613 } |
369 ngx_http_vars_hash_key(key, &cv->name); | 614 |
370 | 615 return NGX_OK; |
371 vp = ngx_array_push(&ngx_http_core_variables_hash[key]); | 616 } |
372 if (vp == NULL) { | 617 |
373 return NGX_ERROR; | 618 |
374 } | 619 ngx_int_t |
375 | 620 ngx_http_variables_init_vars(ngx_conf_t *cf) |
376 *vp = *cv; | 621 { |
377 } | 622 ngx_uint_t i, n; |
378 | 623 ngx_http_variable_t *v, *av; |
379 | 624 ngx_http_core_main_conf_t *cmcf; |
380 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); | 625 |
626 /* set the handlers for the indexed http variables */ | |
627 | |
628 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
381 | 629 |
382 v = cmcf->variables.elts; | 630 v = cmcf->variables.elts; |
631 av = cmcf->all_variables.elts; | |
632 | |
383 for (i = 0; i < cmcf->variables.nelts; i++) { | 633 for (i = 0; i < cmcf->variables.nelts; i++) { |
384 | 634 |
385 if (v[i].handler) { | 635 for (n = 0; n < cmcf->all_variables.nelts; n++) { |
386 continue; | 636 |
387 } | 637 if (v[i].name.len == av[n].name.len |
388 | 638 && ngx_strncmp(v[i].name.data, av[n].name.data, v[i].name.len) |
389 ngx_http_vars_hash_key(key, &v[i].name); | 639 == 0) |
390 | 640 { |
391 cv = ngx_http_core_variables_hash[key].elts; | 641 v[i].handler = av[n].handler; |
392 for (j = 0; j < ngx_http_core_variables_hash[key].nelts; j++) { | 642 v[i].data = av[n].data; |
393 if (cv[j].name.len != v[i].name.len) { | 643 v[i].flags = av[n].flags; |
394 continue; | 644 |
645 goto next; | |
395 } | 646 } |
396 | 647 } |
397 if (ngx_strncmp(cv[j].name.data, v[i].name.data, v[i].name.len) | 648 |
398 == 0) | 649 if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { |
399 { | |
400 v[i].handler = cv[j].handler; | |
401 v[i].data = cv[j].data; | |
402 continue; | |
403 } | |
404 } | |
405 | |
406 if (ngx_strncmp(v[i].name.data, "HTTP_", 5) == 0) { | |
407 v[i].handler = ngx_http_variable_unknown_header; | 650 v[i].handler = ngx_http_variable_unknown_header; |
408 v[i].data = (uintptr_t) &v[i].name; | 651 v[i].data = (uintptr_t) &v[i].name; |
652 | |
409 continue; | 653 continue; |
410 } | 654 } |
411 | 655 |
412 ngx_log_error(NGX_LOG_ERR, cycle->log, 0, | 656 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, |
413 "unknown \"%V\" variable", &v[i].name); | 657 "unknown \"%V\" variable", &v[i].name); |
414 | 658 |
415 return NGX_ERROR; | 659 return NGX_ERROR; |
416 } | 660 |
661 next: | |
662 continue; | |
663 } | |
664 | |
665 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, | |
666 "http variables: %ui", cmcf->variables.nelts); | |
667 | |
668 | |
669 /* init the all http variables hash */ | |
670 | |
671 cmcf->variables_hash.max_size = 500; | |
672 cmcf->variables_hash.bucket_limit = 1; | |
673 cmcf->variables_hash.bucket_size = sizeof(ngx_http_variable_t); | |
674 cmcf->variables_hash.name = "http variables"; | |
675 | |
676 if (ngx_hash_init(&cmcf->variables_hash, cf->pool, | |
677 cmcf->all_variables.elts, cmcf->all_variables.nelts) != NGX_OK) | |
678 { | |
679 return NGX_ERROR; | |
680 } | |
681 | |
682 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0, | |
683 "http variables hash size: %ui for %ui values, " | |
684 "max buckets per entry: %ui", | |
685 cmcf->variables_hash.hash_size, cmcf->all_variables.nelts, | |
686 cmcf->variables_hash.min_buckets); | |
417 | 687 |
418 return NGX_OK; | 688 return NGX_OK; |
419 } | 689 } |