comparison src/http/modules/ngx_http_proxy_module.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 dad2fe8ecf08
children df17fbafec8f
comparison
equal deleted inserted replaced
121:737953b238a4 122:d25a1d6034f1
35 typedef struct { 35 typedef struct {
36 ngx_http_upstream_conf_t upstream; 36 ngx_http_upstream_conf_t upstream;
37 37
38 ngx_peers_t *peers; 38 ngx_peers_t *peers;
39 39
40 ngx_array_t *flushes;
40 ngx_array_t *headers_set_len; 41 ngx_array_t *headers_set_len;
41 ngx_array_t *headers_set; 42 ngx_array_t *headers_set;
42 ngx_hash_t *headers_set_hash; 43 ngx_hash_t *headers_set_hash;
43 44
44 ngx_array_t *headers_source; 45 ngx_array_t *headers_source;
73 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r); 74 static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
74 static void ngx_http_proxy_abort_request(ngx_http_request_t *r); 75 static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
75 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, 76 static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
76 ngx_int_t rc); 77 ngx_int_t rc);
77 78
78 static ngx_http_variable_value_t * 79 static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
79 ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data); 80 ngx_http_variable_value_t *v, uintptr_t data);
80 static ngx_http_variable_value_t * 81 static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
81 ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data); 82 ngx_http_variable_value_t *v, uintptr_t data);
82 static ngx_http_variable_value_t * 83 static ngx_int_t
83 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, 84 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
84 uintptr_t data); 85 ngx_http_variable_value_t *v, uintptr_t data);
85 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, 86 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
86 ngx_table_elt_t *h, size_t prefix); 87 ngx_table_elt_t *h, size_t prefix);
87 88
88 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); 89 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
89 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); 90 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
429 430
430 len += method.len + u->conf->uri.len; 431 len += method.len + u->conf->uri.len;
431 432
432 escape = 0; 433 escape = 0;
433 434
434 loc_len = r->valid_location ? u->conf->location->len : 0; 435 loc_len = r->valid_location ? u->conf->location.len : 0;
435 436
436 if (u->conf->uri.len == 0 && r->valid_unparsed_uri) { 437 if (u->conf->uri.len == 0 && r->valid_unparsed_uri) {
437 len += r->unparsed_uri.len; 438 len += r->unparsed_uri.len;
438 439
439 } else { 440 } else {
445 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len; 446 len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len;
446 } 447 }
447 448
448 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); 449 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
449 450
451 ngx_http_script_flush_no_cachable_variables(r, plcf->flushes);
452
450 le.ip = plcf->headers_set_len->elts; 453 le.ip = plcf->headers_set_len->elts;
451 le.request = r; 454 le.request = r;
455 le.flushed = 1;
452 456
453 while (*(uintptr_t *) le.ip) { 457 while (*(uintptr_t *) le.ip) {
454 while (*(uintptr_t *) le.ip) { 458 while (*(uintptr_t *) le.ip) {
455 lcode = *(ngx_http_script_len_code_pt *) le.ip; 459 lcode = *(ngx_http_script_len_code_pt *) le.ip;
456 len += lcode(&le); 460 len += lcode(&le);
504 cl->buf = b; 508 cl->buf = b;
505 509
506 510
507 /* the request line */ 511 /* the request line */
508 512
509 b->last = ngx_cpymem(b->last, method.data, method.len); 513 b->last = ngx_copy(b->last, method.data, method.len);
510 514
511 u->uri.data = b->last; 515 u->uri.data = b->last;
512 516
513 if (u->conf->uri.len == 0 && r->valid_unparsed_uri) { 517 if (u->conf->uri.len == 0 && r->valid_unparsed_uri) {
514 b->last = ngx_cpymem(b->last, r->unparsed_uri.data, 518 b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
515 r->unparsed_uri.len); 519
516 } else { 520 } else {
517 if (r->valid_location) { 521 if (r->valid_location) {
518 b->last = ngx_cpymem(b->last, u->conf->uri.data, u->conf->uri.len); 522 b->last = ngx_copy(b->last, u->conf->uri.data, u->conf->uri.len);
519 } 523 }
520 524
521 if (escape) { 525 if (escape) {
522 ngx_escape_uri(b->last, r->uri.data + loc_len, 526 ngx_escape_uri(b->last, r->uri.data + loc_len,
523 r->uri.len - loc_len, NGX_ESCAPE_URI); 527 r->uri.len - loc_len, NGX_ESCAPE_URI);
524 b->last += r->uri.len - loc_len + escape; 528 b->last += r->uri.len - loc_len + escape;
525 529
526 } else { 530 } else {
527 b->last = ngx_cpymem(b->last, r->uri.data + loc_len, 531 b->last = ngx_copy(b->last, r->uri.data + loc_len,
528 r->uri.len - loc_len); 532 r->uri.len - loc_len);
529 } 533 }
530 534
531 if (r->args.len > 0) { 535 if (r->args.len > 0) {
532 *b->last++ = '?'; 536 *b->last++ = '?';
533 b->last = ngx_cpymem(b->last, r->args.data, r->args.len); 537 b->last = ngx_copy(b->last, r->args.data, r->args.len);
534 } 538 }
535 } 539 }
536 540
537 u->uri.len = b->last - u->uri.data; 541 u->uri.len = b->last - u->uri.data;
538 542
541 545
542 546
543 e.ip = plcf->headers_set->elts; 547 e.ip = plcf->headers_set->elts;
544 e.pos = b->last; 548 e.pos = b->last;
545 e.request = r; 549 e.request = r;
550 e.flushed = 1;
546 551
547 le.ip = plcf->headers_set_len->elts; 552 le.ip = plcf->headers_set_len->elts;
548 553
549 while (*(uintptr_t *) le.ip) { 554 while (*(uintptr_t *) le.ip) {
550 lcode = *(ngx_http_script_len_code_pt *) le.ip; 555 lcode = *(ngx_http_script_len_code_pt *) le.ip;
598 && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0) 603 && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
599 { 604 {
600 continue; 605 continue;
601 } 606 }
602 607
603 b->last = ngx_cpymem(b->last, header[i].key.data, 608 b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
604 header[i].key.len);
605 609
606 *b->last++ = ':'; *b->last++ = ' '; 610 *b->last++ = ':'; *b->last++ = ' ';
607 611
608 b->last = ngx_cpymem(b->last, header[i].value.data, 612 b->last = ngx_copy(b->last, header[i].value.data,
609 header[i].value.len); 613 header[i].value.len);
610 614
611 *b->last++ = CR; *b->last++ = LF; 615 *b->last++ = CR; *b->last++ = LF;
612 616
613 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 617 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
614 "http proxy header: \"%V: %V\"", 618 "http proxy header: \"%V: %V\"",
733 u->headers_in.status_line.data = ngx_palloc(r->pool, 737 u->headers_in.status_line.data = ngx_palloc(r->pool,
734 u->headers_in.status_line.len); 738 u->headers_in.status_line.len);
735 if (u->headers_in.status_line.data == NULL) { 739 if (u->headers_in.status_line.data == NULL) {
736 return NGX_HTTP_INTERNAL_SERVER_ERROR; 740 return NGX_HTTP_INTERNAL_SERVER_ERROR;
737 } 741 }
742
738 ngx_memcpy(u->headers_in.status_line.data, p->status_start, 743 ngx_memcpy(u->headers_in.status_line.data, p->status_start,
739 u->headers_in.status_line.len); 744 u->headers_in.status_line.len);
740 745
741 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 746 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
742 "http proxy status %ui \"%V\"", 747 "http proxy status %ui \"%V\"",
1052 1057
1053 return; 1058 return;
1054 } 1059 }
1055 1060
1056 1061
1057 static ngx_http_variable_value_t * 1062 static ngx_int_t
1058 ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data) 1063 ngx_http_proxy_host_variable(ngx_http_request_t *r,
1064 ngx_http_variable_value_t *v, uintptr_t data)
1059 { 1065 {
1060 ngx_http_variable_value_t *vv;
1061 ngx_http_proxy_loc_conf_t *plcf; 1066 ngx_http_proxy_loc_conf_t *plcf;
1062 1067
1063 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
1064 if (vv == NULL) {
1065 return NULL;
1066 }
1067
1068 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 1068 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1069 1069
1070 vv->value = 0; 1070 v->len = plcf->host_header.len;
1071 vv->text = plcf->host_header; 1071 v->valid = 1;
1072 1072 v->no_cachable = 0;
1073 return vv; 1073 v->not_found = 0;
1074 v->data = plcf->host_header.data;
1075
1076 return NGX_OK;
1074 } 1077 }
1075 1078
1076 1079
1077 static ngx_http_variable_value_t * 1080 static ngx_int_t
1078 ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data) 1081 ngx_http_proxy_port_variable(ngx_http_request_t *r,
1082 ngx_http_variable_value_t *v, uintptr_t data)
1079 { 1083 {
1080 ngx_http_variable_value_t *vv;
1081 ngx_http_proxy_loc_conf_t *plcf; 1084 ngx_http_proxy_loc_conf_t *plcf;
1082 1085
1083 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
1084 if (vv == NULL) {
1085 return NULL;
1086 }
1087
1088 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 1086 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1089 1087
1090 vv->value = 0; 1088 v->len = plcf->port_text.len;
1091 vv->text = plcf->port_text; 1089 v->valid = 1;
1092 1090 v->no_cachable = 0;
1093 return vv; 1091 v->not_found = 0;
1092 v->data = plcf->port_text.data;
1093
1094 return NGX_OK;
1094 } 1095 }
1095 1096
1096 1097
1097 static ngx_http_variable_value_t * 1098 static ngx_int_t
1098 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, 1099 ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
1099 uintptr_t data) 1100
1101 ngx_http_variable_value_t *v, uintptr_t data)
1100 { 1102 {
1101 u_char *p; 1103 u_char *p;
1102 ngx_http_variable_value_t *vv; 1104
1103 1105 v->valid = 1;
1104 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 1106 v->no_cachable = 0;
1105 if (vv == NULL) { 1107 v->not_found = 0;
1106 return NULL;
1107 }
1108
1109 vv->value = 0;
1110 1108
1111 if (r->headers_in.x_forwarded_for == NULL) { 1109 if (r->headers_in.x_forwarded_for == NULL) {
1112 vv->text = r->connection->addr_text; 1110 v->len = r->connection->addr_text.len;
1113 return vv; 1111 v->data = r->connection->addr_text.data;
1114 } 1112 return NGX_OK;
1115 1113 }
1116 vv->text.len = r->headers_in.x_forwarded_for->value.len 1114
1117 + sizeof(", ") - 1 + r->connection->addr_text.len; 1115 v->len = r->headers_in.x_forwarded_for->value.len
1118 1116 + sizeof(", ") - 1 + r->connection->addr_text.len;
1119 p = ngx_palloc(r->pool, vv->text.len); 1117
1118 p = ngx_palloc(r->pool, v->len);
1120 if (p == NULL) { 1119 if (p == NULL) {
1121 return NULL; 1120 return NGX_ERROR;
1122 } 1121 }
1123 1122
1124 vv->text.data = p; 1123 v->data = p;
1125 1124
1126 p = ngx_cpymem(p, r->headers_in.x_forwarded_for->value.data, 1125 p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
1127 r->headers_in.x_forwarded_for->value.len); 1126 r->headers_in.x_forwarded_for->value.len);
1128 1127
1129 *p++ = ','; *p++ = ' '; 1128 *p++ = ','; *p++ = ' ';
1130 1129
1131 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); 1130 ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
1132 1131
1133 return vv; 1132 return NGX_OK;
1134 } 1133 }
1135 1134
1136 1135
1137 static ngx_int_t 1136 static ngx_int_t
1138 ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h, 1137 ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
1184 return NGX_ERROR; 1183 return NGX_ERROR;
1185 } 1184 }
1186 1185
1187 p = data; 1186 p = data;
1188 1187
1189 if (prefix) { 1188 p = ngx_copy(p, h->value.data, prefix);
1190 p = ngx_cpymem(p, h->value.data, prefix); 1189
1191 } 1190 p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len);
1192
1193 p = ngx_cpymem(p, pr->replacement.text.data, pr->replacement.text.len);
1194 1191
1195 ngx_memcpy(p, h->value.data + prefix + pr->redirect.len, 1192 ngx_memcpy(p, h->value.data + prefix + pr->redirect.len,
1196 h->value.len - pr->redirect.len - prefix); 1193 h->value.len - pr->redirect.len - prefix);
1197 1194
1198 h->value.len = len; 1195 h->value.len = len;
1233 return NGX_ERROR; 1230 return NGX_ERROR;
1234 } 1231 }
1235 1232
1236 p = data; 1233 p = data;
1237 1234
1238 if (prefix) { 1235 p = ngx_copy(p, h->value.data, prefix);
1239 p = ngx_cpymem(p, h->value.data, prefix);
1240 }
1241 1236
1242 e.ip = pr->replacement.vars.values; 1237 e.ip = pr->replacement.vars.values;
1243 e.pos = p; 1238 e.pos = p;
1244 1239
1245 while (*(uintptr_t *) e.ip) { 1240 while (*(uintptr_t *) e.ip) {
1528 return NGX_CONF_ERROR; 1523 return NGX_CONF_ERROR;
1529 } 1524 }
1530 1525
1531 pr->handler = ngx_http_proxy_rewrite_redirect_text; 1526 pr->handler = ngx_http_proxy_rewrite_redirect_text;
1532 pr->redirect = conf->upstream.url; 1527 pr->redirect = conf->upstream.url;
1533 pr->replacement.text = *conf->upstream.location; 1528 pr->replacement.text = conf->upstream.location;
1534 } 1529 }
1535 } 1530 }
1536 1531
1537 1532
1538 if (conf->peers == NULL) { 1533 if (conf->peers == NULL) {
1539 conf->peers = prev->peers; 1534 conf->peers = prev->peers;
1540 } 1535 }
1541 1536
1542 if (conf->headers_source == NULL) { 1537 if (conf->headers_source == NULL) {
1543 conf->headers_source = prev->headers_source; 1538 conf->flushes = prev->flushes;
1544 conf->headers_set_len = prev->headers_set_len; 1539 conf->headers_set_len = prev->headers_set_len;
1545 conf->headers_set = prev->headers_set; 1540 conf->headers_set = prev->headers_set;
1546 conf->headers_set_hash = prev->headers_set_hash; 1541 conf->headers_set_hash = prev->headers_set_hash;
1542 conf->headers_source = prev->headers_source;
1547 } 1543 }
1548 1544
1549 if (conf->headers_set_hash) { 1545 if (conf->headers_set_hash) {
1550 return NGX_CONF_OK; 1546 return NGX_CONF_OK;
1551 } 1547 }
1678 1674
1679 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); 1675 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
1680 1676
1681 sc.cf = cf; 1677 sc.cf = cf;
1682 sc.source = &src[i].value; 1678 sc.source = &src[i].value;
1679 sc.flushes = &conf->flushes;
1683 sc.lengths = &conf->headers_set_len; 1680 sc.lengths = &conf->headers_set_len;
1684 sc.values = &conf->headers_set; 1681 sc.values = &conf->headers_set;
1685 1682
1686 if (ngx_http_script_compile(&sc) != NGX_OK) { 1683 if (ngx_http_script_compile(&sc) != NGX_OK) {
1687 return NGX_CONF_ERROR; 1684 return NGX_CONF_ERROR;
1841 1838
1842 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); 1839 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
1843 1840
1844 clcf->handler = ngx_http_proxy_handler; 1841 clcf->handler = ngx_http_proxy_handler;
1845 1842
1846 plcf->upstream.location = &clcf->name; 1843 plcf->upstream.location = clcf->name;
1847 1844
1848 #if (NGX_PCRE) 1845 #if (NGX_PCRE)
1849 1846
1850 if (clcf->regex && plcf->upstream.uri.len) { 1847 if (clcf->regex) {
1851 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1848 if (plcf->upstream.uri.len) {
1852 "\"proxy_pass\" may not have URI part in " 1849 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1853 "location given by regular expression"); 1850 "\"proxy_pass\" may not have URI part in "
1854 return NGX_CONF_ERROR; 1851 "location given by regular expression");
1852 return NGX_CONF_ERROR;
1853 }
1854
1855 plcf->upstream.location.len = 0;
1855 } 1856 }
1856 1857
1857 #endif 1858 #endif
1858 1859
1859 plcf->upstream.url = *url; 1860 plcf->upstream.url = *url;
1909 return NGX_CONF_ERROR; 1910 return NGX_CONF_ERROR;
1910 } 1911 }
1911 1912
1912 pr->handler = ngx_http_proxy_rewrite_redirect_text; 1913 pr->handler = ngx_http_proxy_rewrite_redirect_text;
1913 pr->redirect = plcf->upstream.url; 1914 pr->redirect = plcf->upstream.url;
1914 pr->replacement.text = *plcf->upstream.location; 1915 pr->replacement.text = plcf->upstream.location;
1915 1916
1916 return NGX_CONF_OK; 1917 return NGX_CONF_OK;
1917 } 1918 }
1918 1919
1919 if (ngx_http_script_variables_count(&value[2]) == 0) { 1920 if (ngx_http_script_variables_count(&value[2]) == 0) {