comparison src/http/ngx_http_variables.c @ 122:d25a1d6034f1 NGINX_0_3_8

nginx 0.3.8 *) Security: nginx now checks URI got from a backend in "X-Accel-Redirect" header line or in SSI file for the "/../" paths and zeroes. *) Change: nginx now does not treat the empty user name in the "Authorization" header line as valid one. *) Feature: the "ssl_session_timeout" directives of the ngx_http_ssl_module and ngx_imap_ssl_module. *) Feature: the "auth_http_header" directive of the ngx_imap_auth_http_module. *) Feature: the "add_header" directive. *) Feature: the ngx_http_realip_module. *) Feature: the new variables to use in the "log_format" directive: $bytes_sent, $apache_bytes_sent, $status, $time_gmt, $uri, $request_time, $request_length, $upstream_status, $upstream_response_time, $gzip_ratio, $uid_got, $uid_set, $connection, $pipe, and $msec. The parameters in the "%name" form will be canceled soon. *) Change: now the false variable values in the "if" directive are the empty string "" and string starting with "0". *) Bugfix: while using proxied or FastCGI-server nginx may leave connections and temporary files with client requests in open state. *) Bugfix: the worker processes did not flush the buffered logs on graceful exit. *) Bugfix: if the request URI was changes by the "rewrite" directive and the request was proxied in location given by regular expression, then the incorrect request was transferred to backend; bug appeared in 0.2.6. *) Bugfix: the "expires" directive did not remove the previous "Expires" header. *) Bugfix: nginx may stop to accept requests if the "rtsig" method and several worker processes were used. *) Bugfix: the "\"" and "\'" escape symbols were incorrectly handled in SSI commands. *) Bugfix: if the response was ended just after the SSI command and gzipping was used, then the response did not transferred complete or did not transferred at all.
author Igor Sysoev <http://sysoev.ru>
date Wed, 09 Nov 2005 00:00:00 +0300
parents e85dca77c46a
children df17fbafec8f
comparison
equal deleted inserted replaced
121:737953b238a4 122:d25a1d6034f1
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 static ngx_http_variable_value_t * 13 static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
14 ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data); 14 ngx_http_variable_value_t *v, uintptr_t data);
15 static ngx_http_variable_value_t * 15 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
16 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data); 16 ngx_http_variable_value_t *v, uintptr_t data);
17 static ngx_http_variable_value_t * 17 static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
18 ngx_http_variable_headers(ngx_http_request_t *r, uintptr_t data); 18 ngx_http_variable_value_t *v, uintptr_t data);
19 static ngx_http_variable_value_t * 19 static ngx_int_t ngx_http_variable_unknown_header(ngx_http_request_t *r,
20 ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data); 20 ngx_http_variable_value_t *v, uintptr_t data);
21 static ngx_http_variable_value_t * 21 static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
22 ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data); 22 ngx_http_variable_value_t *v, uintptr_t data);
23 static ngx_http_variable_value_t * 23 static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
24 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data); 24 ngx_http_variable_value_t *v, uintptr_t data);
25 static ngx_http_variable_value_t * 25 static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
26 ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data); 26 ngx_http_variable_value_t *v, uintptr_t data);
27 static ngx_http_variable_value_t * 27 static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
28 ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data); 28 ngx_http_variable_value_t *v, uintptr_t data);
29 static ngx_http_variable_value_t * 29 static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
30 ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data); 30 ngx_http_variable_value_t *v, uintptr_t data);
31 static ngx_http_variable_value_t * 31 static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
32 ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data); 32 ngx_http_variable_value_t *v, uintptr_t data);
33 static ngx_http_variable_value_t * 33 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
34 ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data); 34 ngx_http_variable_value_t *v, uintptr_t data);
35 static ngx_http_variable_value_t * 35 static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
36 ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data); 36 ngx_http_variable_value_t *v, uintptr_t data);
37 static ngx_http_variable_value_t * 37 static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
38 ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data); 38 ngx_http_variable_value_t *v, uintptr_t data);
39 static ngx_http_variable_value_t *
40 ngx_http_variable_sent(ngx_http_request_t *r, uintptr_t data);
41 39
42 40
43 /* 41 /*
44 * TODO: 42 * TODO:
45 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED 43 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
93 offsetof(ngx_http_request_t, http_protocol), 0, 0 }, 91 offsetof(ngx_http_request_t, http_protocol), 0, 0 },
94 92
95 { ngx_string("request_uri"), ngx_http_variable_request, 93 { ngx_string("request_uri"), ngx_http_variable_request,
96 offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, 94 offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
97 95
96 { ngx_string("uri"), ngx_http_variable_request,
97 offsetof(ngx_http_request_t, uri),
98 NGX_HTTP_VAR_NOCACHABLE, 0 },
99
98 { ngx_string("document_uri"), ngx_http_variable_request, 100 { ngx_string("document_uri"), ngx_http_variable_request,
99 offsetof(ngx_http_request_t, uri), 0, 0 }, 101 offsetof(ngx_http_request_t, uri),
102 NGX_HTTP_VAR_NOCACHABLE, 0 },
100 103
101 { ngx_string("request"), ngx_http_variable_request, 104 { ngx_string("request"), ngx_http_variable_request,
102 offsetof(ngx_http_request_t, request_line), 0, 0 }, 105 offsetof(ngx_http_request_t, request_line), 0, 0 },
103 106
104 { ngx_string("document_root"), ngx_http_variable_document_root, 0, 0, 0 }, 107 { ngx_string("document_root"), ngx_http_variable_document_root, 0, 0, 0 },
114 offsetof(ngx_http_request_t, server_name), 0, 0 }, 117 offsetof(ngx_http_request_t, server_name), 0, 0 },
115 118
116 { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 }, 119 { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 },
117 120
118 { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 }, 121 { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 },
119
120 { ngx_string("sent"), ngx_http_variable_sent, 0, 0, 0 },
121
122 { ngx_string("apache_sent"), ngx_http_variable_sent, 1, 0, 0 },
123 122
124 { ngx_null_string, NULL, 0, 0, 0 } 123 { ngx_null_string, NULL, 0, 0, 0 }
125 }; 124 };
126 125
127 126
231 230
232 ngx_http_variable_value_t * 231 ngx_http_variable_value_t *
233 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) 232 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
234 { 233 {
235 ngx_http_variable_t *v; 234 ngx_http_variable_t *v;
236 ngx_http_variable_value_t *vv;
237 ngx_http_core_main_conf_t *cmcf; 235 ngx_http_core_main_conf_t *cmcf;
238 236
239 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 237 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
240 238
241 if (cmcf->variables.nelts <= index) { 239 if (cmcf->variables.nelts <= index) {
242 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, 240 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
243 "unknown variable index: %d", index); 241 "unknown variable index: %d", index);
244 return NULL; 242 return NULL;
245 } 243 }
246 244
247 if (r->variables && r->variables[index]) { 245 if (r->variables[index].not_found || r->variables[index].valid) {
248 return r->variables[index]; 246 return &r->variables[index];
249 } 247 }
250 248
251 v = cmcf->variables.elts; 249 v = cmcf->variables.elts;
252 250
253 vv = v[index].handler(r, v[index].data); 251 if (v[index].handler(r, &r->variables[index], v[index].data) == NGX_OK) {
254 252
255 if (r->variables == NULL) { 253 if (v[index].flags & NGX_HTTP_VAR_NOCACHABLE) {
256 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts 254 r->variables[index].no_cachable = 1;
257 * sizeof(ngx_http_variable_value_t *)); 255 }
258 if (r->variables == NULL) { 256
259 return NULL; 257 return &r->variables[index];
260 } 258 }
261 } 259
262 260 return NULL;
263 if (!(v[index].flags & NGX_HTTP_VAR_NOCACHABLE)) { 261 }
264 r->variables[index] = vv; 262
265 } 263
266 264 ngx_http_variable_value_t *
267 return vv; 265 ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
266 {
267 ngx_http_variable_value_t *v;
268
269 v = &r->variables[index];
270
271 if (v->valid) {
272 if (!v->no_cachable) {
273 return v;
274 }
275
276 v->valid = 0;
277 v->not_found = 0;
278 }
279
280 return ngx_http_get_indexed_variable(r, index);
268 } 281 }
269 282
270 283
271 ngx_http_variable_value_t * 284 ngx_http_variable_value_t *
272 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) 285 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name)
273 { 286 {
274 ngx_uint_t i, key; 287 ngx_uint_t i, key;
275 ngx_http_variable_t *v; 288 ngx_http_variable_t *v;
289 ngx_http_variable_value_t *vv;
276 ngx_http_core_main_conf_t *cmcf; 290 ngx_http_core_main_conf_t *cmcf;
277 291
278 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 292 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
279 293
280 key = 0; 294 key = 0;
290 { 304 {
291 if (v[key].flags & NGX_HTTP_VAR_INDEXED) { 305 if (v[key].flags & NGX_HTTP_VAR_INDEXED) {
292 return ngx_http_get_indexed_variable(r, v[key].index); 306 return ngx_http_get_indexed_variable(r, v[key].index);
293 307
294 } else { 308 } else {
295 return v[key].handler(r, v[key].data); 309
296 } 310 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
297 } 311
298 312 if (vv && v[key].handler(r, vv, v[key].data) == NGX_OK) {
299 if (ngx_strncmp(name->data, "http_", 5) == 0) { 313 return vv;
300 return ngx_http_variable_unknown_header(r, (uintptr_t) name); 314 }
301 } 315
302 316 return NULL;
303 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 317 }
304 "unknown \"%V\" variable", name);
305
306 return NGX_HTTP_VAR_NOT_FOUND;
307 }
308
309
310 static ngx_http_variable_value_t *
311 ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data)
312 {
313 ngx_str_t *s;
314 ngx_http_variable_value_t *vv;
315
316 s = (ngx_str_t *) ((char *) r + data);
317
318 if (s->data == NULL) {
319 return NGX_HTTP_VAR_NOT_FOUND;
320 } 318 }
321 319
322 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 320 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
323 if (vv == NULL) { 321 if (vv == NULL) {
324 return NULL; 322 return NULL;
325 } 323 }
326 324
327 vv->value = 0; 325 if (ngx_strncmp(name->data, "http_", 5) == 0) {
328 vv->text = *s; 326
327 if (ngx_http_variable_unknown_header(r, vv, (uintptr_t) name) == NGX_OK)
328 {
329 return vv;
330 }
331
332 return NULL;
333 }
334
335 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
336 "unknown \"%V\" variable", name);
337
338 vv->not_found = 1;
329 339
330 return vv; 340 return vv;
331 } 341 }
332 342
333 343
334 static ngx_http_variable_value_t * 344 static ngx_int_t
335 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data) 345 ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
336 { 346 uintptr_t data)
337 ngx_table_elt_t *h; 347 {
338 ngx_http_variable_value_t *vv; 348 ngx_str_t *s;
349
350 s = (ngx_str_t *) ((char *) r + data);
351
352 if (s->data) {
353 v->len = s->len;
354 v->valid = 1;
355 v->no_cachable = 0;
356 v->not_found = 0;
357 v->data = s->data;
358
359 } else {
360 v->not_found = 1;
361 }
362
363 return NGX_OK;
364 }
365
366
367 static ngx_int_t
368 ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
369 uintptr_t data)
370 {
371 ngx_table_elt_t *h;
339 372
340 h = *(ngx_table_elt_t **) ((char *) r + data); 373 h = *(ngx_table_elt_t **) ((char *) r + data);
341 374
342 if (h == NULL) { 375 if (h) {
343 return NGX_HTTP_VAR_NOT_FOUND; 376 v->len = h->value.len;
344 } 377 v->valid = 1;
345 378 v->no_cachable = 0;
346 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 379 v->not_found = 0;
347 if (vv == NULL) { 380 v->data = h->value.data;
348 return NULL; 381
349 } 382 } else {
350 383 v->not_found = 1;
351 vv->value = 0; 384 }
352 vv->text = h->value; 385
353 386 return NGX_OK;
354 return vv; 387 }
355 } 388
356 389
357 390 static ngx_int_t
358 static ngx_http_variable_value_t * 391 ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
359 ngx_http_variable_headers(ngx_http_request_t *r, uintptr_t data) 392 uintptr_t data)
360 { 393 {
361 u_char *p; 394 size_t len;
362 ngx_uint_t i; 395 u_char *p;
363 ngx_array_t *a; 396 ngx_uint_t i;
364 ngx_table_elt_t **h; 397 ngx_array_t *a;
365 ngx_http_variable_value_t *vv; 398 ngx_table_elt_t **h;
366 399
367 a = (ngx_array_t *) ((char *) r + data); 400 a = (ngx_array_t *) ((char *) r + data);
368 401
369 if (a->nelts == 0) { 402 if (a->nelts == 0) {
370 return NGX_HTTP_VAR_NOT_FOUND; 403 v->not_found = 1;
371 } 404 return NGX_OK;
372 405 }
373 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 406
374 if (vv == NULL) { 407 v->valid = 1;
375 return NULL; 408 v->no_cachable = 0;
376 } 409 v->not_found = 0;
377
378 vv->value = 0;
379 410
380 h = a->elts; 411 h = a->elts;
381 412
382 if (a->nelts == 1) { 413 if (a->nelts == 1) {
383 vv->text = (*h)->value; 414 v->len = (*h)->value.len;
384 return vv; 415 v->data = (*h)->value.data;
385 } 416
386 417 return NGX_OK;
387 vv->text.len = (size_t) - (ssize_t) (sizeof("; ") - 1); 418 }
419
420 len = (size_t) - (ssize_t) (sizeof("; ") - 1);
388 421
389 for (i = 0; i < a->nelts; i++) { 422 for (i = 0; i < a->nelts; i++) {
390 vv->text.len += h[i]->value.len + sizeof("; ") - 1; 423 len += h[i]->value.len + sizeof("; ") - 1;
391 } 424 }
392 425
393 vv->text.data = ngx_palloc(r->pool, vv->text.len); 426 p = ngx_palloc(r->pool, len);
394 if (vv->text.data == NULL) { 427 if (p == NULL) {
395 return NULL; 428 return NGX_ERROR;
396 } 429 }
397 430
398 p = vv->text.data; 431 v->len = len;
432 v->data = p;
399 433
400 for (i = 0; /* void */ ; i++) { 434 for (i = 0; /* void */ ; i++) {
401 p = ngx_cpymem(p, h[i]->value.data, h[i]->value.len); 435 p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
402 436
403 if (i == a->nelts - 1) { 437 if (i == a->nelts - 1) {
404 break; 438 break;
405 } 439 }
406 440
407 *p++ = ';'; *p++ = ' '; 441 *p++ = ';'; *p++ = ' ';
408 } 442 }
409 443
410 return vv; 444 return NGX_OK;
411 } 445 }
412 446
413 447
414 static ngx_http_variable_value_t * 448 static ngx_int_t
415 ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data) 449 ngx_http_variable_unknown_header(ngx_http_request_t *r,
450 ngx_http_variable_value_t *v, uintptr_t data)
416 { 451 {
417 ngx_str_t *var = (ngx_str_t *) data; 452 ngx_str_t *var = (ngx_str_t *) data;
418 453
419 u_char ch; 454 u_char ch;
420 ngx_uint_t i, n; 455 ngx_uint_t i, n;
421 ngx_list_part_t *part; 456 ngx_list_part_t *part;
422 ngx_table_elt_t *header; 457 ngx_table_elt_t *header;
423 ngx_http_variable_value_t *vv;
424 458
425 part = &r->headers_in.headers.part; 459 part = &r->headers_in.headers.part;
426 header = part->elts; 460 header = part->elts;
427 461
428 for (i = 0; /* void */ ; i++) { 462 for (i = 0; /* void */ ; i++) {
451 break; 485 break;
452 } 486 }
453 } 487 }
454 488
455 if (n + 5 == var->len) { 489 if (n + 5 == var->len) {
456 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 490 v->len = header[i].value.len;
457 if (vv == NULL) { 491 v->valid = 1;
458 return NULL; 492 v->no_cachable = 0;
459 } 493 v->not_found = 0;
460 494 v->data = header[i].value.data;
461 vv->value = 0; 495
462 vv->text = header[i].value; 496 return NGX_OK;
463 return vv; 497 }
464 } 498 }
465 } 499
466 500 v->not_found = 1;
467 return NGX_HTTP_VAR_NOT_FOUND; 501
468 } 502 return NGX_OK;
469 503 }
470 504
471 static ngx_http_variable_value_t * 505
472 ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data) 506 static ngx_int_t
473 { 507 ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
474 ngx_http_variable_value_t *vv; 508 uintptr_t data)
475 509 {
476 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
477 if (vv == NULL) {
478 return NULL;
479 }
480
481 vv->value = 0;
482
483 if (r->headers_in.host) { 510 if (r->headers_in.host) {
484 vv->text.len = r->headers_in.host_name_len; 511 v->len = r->headers_in.host_name_len;
485 vv->text.data = r->headers_in.host->value.data; 512 v->data = r->headers_in.host->value.data;
486 513
487 } else { 514 } else {
488 vv->text = r->server_name; 515 v->len = r->server_name.len;
489 } 516 v->data = r->server_name.data;
490 517 }
491 return vv; 518
492 } 519 v->valid = 1;
493 520 v->no_cachable = 0;
494 521 v->not_found = 0;
495 static ngx_http_variable_value_t * 522
496 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data) 523 return NGX_OK;
497 { 524 }
498 ngx_http_variable_value_t *vv; 525
499 526
500 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 527 static ngx_int_t
501 if (vv == NULL) { 528 ngx_http_variable_remote_addr(ngx_http_request_t *r,
502 return NULL; 529 ngx_http_variable_value_t *v, uintptr_t data)
503 } 530 {
504 531 v->len = r->connection->addr_text.len;
505 vv->value = 0; 532 v->valid = 1;
506 vv->text = r->connection->addr_text; 533 v->no_cachable = 0;
507 534 v->not_found = 0;
508 return vv; 535 v->data = r->connection->addr_text.data;
509 } 536
510 537 return NGX_OK;
511 538 }
512 static ngx_http_variable_value_t * 539
513 ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data) 540
514 { 541 static ngx_int_t
515 ngx_uint_t port; 542 ngx_http_variable_remote_port(ngx_http_request_t *r,
516 struct sockaddr_in *sin; 543 ngx_http_variable_value_t *v, uintptr_t data)
517 ngx_http_variable_value_t *vv; 544 {
518 545 ngx_uint_t port;
519 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 546 struct sockaddr_in *sin;
520 if (vv == NULL) { 547
521 return NULL; 548 v->len = 0;
522 } 549 v->valid = 1;
523 550 v->no_cachable = 0;
524 vv->value = 0; 551 v->not_found = 0;
525 vv->text.len = 0; 552
526 553 v->data = ngx_palloc(r->pool, sizeof("65535") - 1);
527 vv->text.data = ngx_palloc(r->pool, sizeof("65535") - 1); 554 if (v->data == NULL) {
528 if (vv->text.data == NULL) { 555 return NGX_ERROR;
529 return NULL;
530 } 556 }
531 557
532 /* AF_INET only */ 558 /* AF_INET only */
533 559
534 if (r->connection->sockaddr->sa_family == AF_INET) { 560 if (r->connection->sockaddr->sa_family == AF_INET) {
535 sin = (struct sockaddr_in *) r->connection->sockaddr; 561 sin = (struct sockaddr_in *) r->connection->sockaddr;
536 562
537 port = ntohs(sin->sin_port); 563 port = ntohs(sin->sin_port);
538 564
539 if (port > 0 && port < 65536) { 565 if (port > 0 && port < 65536) {
540 vv->value = port; 566 v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
541 vv->text.len = ngx_sprintf(vv->text.data, "%ui", port) 567 }
542 - vv->text.data; 568 }
543 } 569
544 } 570 return NGX_OK;
545 571 }
546 return vv; 572
547 } 573
548 574 static ngx_int_t
549 575 ngx_http_variable_server_addr(ngx_http_request_t *r,
550 static ngx_http_variable_value_t * 576 ngx_http_variable_value_t *v, uintptr_t data)
551 ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data) 577 {
552 { 578 socklen_t len;
553 socklen_t len; 579 ngx_connection_t *c;
554 ngx_connection_t *c; 580 struct sockaddr_in sin;
555 struct sockaddr_in sin; 581
556 ngx_http_variable_value_t *vv; 582 v->data = ngx_palloc(r->pool, INET_ADDRSTRLEN);
557 583 if (v->data == NULL) {
558 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 584 return NGX_ERROR;
559 if (vv == NULL) {
560 return NULL;
561 }
562
563 vv->value = 0;
564
565 vv->text.data = ngx_palloc(r->pool, INET_ADDRSTRLEN);
566 if (vv->text.data == NULL) {
567 return NULL;
568 } 585 }
569 586
570 c = r->connection; 587 c = r->connection;
571 588
572 if (r->in_addr == 0) { 589 if (r->in_addr == 0) {
573 len = sizeof(struct sockaddr_in); 590 len = sizeof(struct sockaddr_in);
574 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { 591 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
575 ngx_log_error(NGX_LOG_CRIT, c->log, 592 ngx_log_error(NGX_LOG_CRIT, c->log,
576 ngx_socket_errno, "getsockname() failed"); 593 ngx_socket_errno, "getsockname() failed");
577 return NULL; 594 return NGX_ERROR;
578 } 595 }
579 596
580 r->in_addr = sin.sin_addr.s_addr; 597 r->in_addr = sin.sin_addr.s_addr;
581 } 598 }
582 599
583 vv->text.len = ngx_inet_ntop(c->listening->family, &r->in_addr, 600 v->len = ngx_inet_ntop(c->listening->family, &r->in_addr,
584 vv->text.data, INET_ADDRSTRLEN); 601 v->data, INET_ADDRSTRLEN);
585 602 v->valid = 1;
586 return vv; 603 v->no_cachable = 0;
587 } 604 v->not_found = 0;
588 605
589 606 return NGX_OK;
590 static ngx_http_variable_value_t * 607 }
591 ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data) 608
592 { 609
593 ngx_http_variable_value_t *vv; 610 static ngx_int_t
594 611 ngx_http_variable_server_port(ngx_http_request_t *r,
595 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 612 ngx_http_variable_value_t *v, uintptr_t data)
596 if (vv == NULL) { 613 {
597 return NULL; 614 v->len = r->port_text->len - 1;
598 } 615 v->valid = 1;
599 616 v->no_cachable = 0;
600 vv->value = r->port; 617 v->not_found = 0;
601 vv->text.len = r->port_text->len - 1; 618 v->data = r->port_text->data + 1;
602 vv->text.data = r->port_text->data + 1; 619
603 620 return NGX_OK;
604 return vv; 621 }
605 } 622
606 623
607 624 static ngx_int_t
608 static ngx_http_variable_value_t * 625 ngx_http_variable_document_root(ngx_http_request_t *r,
609 ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data) 626 ngx_http_variable_value_t *v, uintptr_t data)
610 { 627 {
611 ngx_http_core_loc_conf_t *clcf; 628 ngx_http_core_loc_conf_t *clcf;
612 ngx_http_variable_value_t *vv;
613
614 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
615 if (vv == NULL) {
616 return NULL;
617 }
618 629
619 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 630 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
620 631
621 vv->value = 0; 632 v->len = clcf->root.len;
622 vv->text = clcf->root; 633 v->valid = 1;
623 634 v->no_cachable = 0;
624 return vv; 635 v->not_found = 0;
625 } 636 v->data = clcf->root.data;
626 637
627 638 return NGX_OK;
628 static ngx_http_variable_value_t * 639 }
629 ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data) 640
630 { 641
631 ngx_http_variable_value_t *vv; 642 static ngx_int_t
632 643 ngx_http_variable_request_filename(ngx_http_request_t *r,
633 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 644 ngx_http_variable_value_t *v, uintptr_t data)
634 if (vv == NULL) { 645 {
635 return NULL; 646 ngx_str_t path;
636 } 647
637 648 if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) {
638 vv->value = 0; 649 return NGX_ERROR;
639
640 if (ngx_http_map_uri_to_path(r, &vv->text, 0) == NULL) {
641 return NULL;
642 } 650 }
643 651
644 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */ 652 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
645 653
646 vv->text.len--; 654 v->len = path.len - 1;
647 655 v->valid = 1;
648 return vv; 656 v->no_cachable = 0;
649 } 657 v->not_found = 0;
650 658 v->data = path.data;
651 659
652 static ngx_http_variable_value_t * 660 return NGX_OK;
653 ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data) 661 }
654 { 662
655 ngx_http_variable_value_t *vv; 663
656 664 static ngx_int_t
657 if (r->method_name.data == NULL) { 665 ngx_http_variable_request_method(ngx_http_request_t *r,
658 return NGX_HTTP_VAR_NOT_FOUND; 666 ngx_http_variable_value_t *v, uintptr_t data)
659 } 667 {
660 668 if (r->method_name.data) {
661 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 669 if (r->upstream && r->upstream->method.len) {
662 if (vv == NULL) { 670 v->len = r->upstream->method.len;
663 return NULL; 671 v->data = r->upstream->method.data;
664 } 672
665 673 } else {
666 vv->value = 0; 674 v->len = r->method_name.len;
667 675 v->data = r->method_name.data;
668 if (r->upstream && r->upstream->method.len) { 676 }
669 vv->text = r->upstream->method; 677
678 v->valid = 1;
679 v->no_cachable = 0;
680 v->not_found = 0;
670 681
671 } else { 682 } else {
672 vv->text = r->method_name; 683 v->not_found = 1;
673 } 684 }
674 685
675 return vv; 686 return NGX_OK;
676 } 687 }
677 688
678 689
679 static ngx_http_variable_value_t * 690 static ngx_int_t
680 ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data) 691 ngx_http_variable_remote_user(ngx_http_request_t *r,
681 { 692 ngx_http_variable_value_t *v, uintptr_t data)
682 ngx_int_t rc; 693 {
683 ngx_http_variable_value_t *vv; 694 ngx_int_t rc;
684 695
685 rc = ngx_http_auth_basic_user(r); 696 rc = ngx_http_auth_basic_user(r);
686 697
687 if (rc == NGX_DECLINED) { 698 if (rc == NGX_DECLINED) {
688 return NGX_HTTP_VAR_NOT_FOUND; 699 v->not_found = 1;
700 return NGX_OK;
689 } 701 }
690 702
691 if (rc == NGX_ERROR) { 703 if (rc == NGX_ERROR) {
692 return NULL; 704 return NGX_ERROR;
693 } 705 }
694 706
695 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 707 v->len = r->headers_in.user.len;
696 if (vv == NULL) { 708 v->valid = 1;
697 return NULL; 709 v->no_cachable = 0;
698 } 710 v->not_found = 0;
699 711 v->data = r->headers_in.user.data;
700 vv->value = 0; 712
701 vv->text = r->headers_in.user; 713 return NGX_OK;
702
703 return vv;
704 }
705
706
707 static ngx_http_variable_value_t *
708 ngx_http_variable_sent(ngx_http_request_t *r, uintptr_t data)
709 {
710 off_t sent;
711 u_char *p;
712 ngx_http_variable_value_t *vv;
713
714 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
715 if (vv == NULL) {
716 return NULL;
717 }
718
719 sent = r->connection->sent;
720
721 if (data) {
722 sent -= r->header_size;
723
724 if (sent < 0) {
725 sent = 0;
726 }
727 }
728
729 p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
730 if (p == NULL) {
731 return NULL;
732 }
733
734 vv->value = 0;
735 vv->text.len = ngx_sprintf(p, "%O", sent) - p;
736 vv->text.data = p;
737
738 return vv;
739 } 714 }
740 715
741 716
742 ngx_int_t 717 ngx_int_t
743 ngx_http_variables_add_core_vars(ngx_conf_t *cf) 718 ngx_http_variables_add_core_vars(ngx_conf_t *cf)