Mercurial > hg > nginx-quic
comparison src/http/ngx_http_variables.c @ 8872:08b3ea81ff5f
Combining unknown headers during variables lookup (ticket #1316).
Previously, $http_*, $sent_http_*, $sent_trailer_*, $upstream_http_*,
and $upstream_trailer_* variables returned only the first header (with
a few specially handled exceptions: $http_cookie, $http_x_forwarded_for,
$sent_http_cache_control, $sent_http_link).
With this change, all headers are returned, combined together. For
example, $http_foo variable will be "a, b" if there are "Foo: a" and
"Foo: b" headers in the request.
Note that $upstream_http_set_cookie will also return all "Set-Cookie"
headers (ticket #1843), though this might not be what one want, since
the "Set-Cookie" header does not follow the list syntax (see RFC 7230,
section 3.2.2).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 30 May 2022 21:25:32 +0300 |
parents | ae7c767aa491 |
children | ef6a3a99a81a |
comparison
equal
deleted
inserted
replaced
8871:8b7a96fdd54c | 8872:08b3ea81ff5f |
---|---|
917 | 917 |
918 static ngx_int_t | 918 static ngx_int_t |
919 ngx_http_variable_unknown_header_in(ngx_http_request_t *r, | 919 ngx_http_variable_unknown_header_in(ngx_http_request_t *r, |
920 ngx_http_variable_value_t *v, uintptr_t data) | 920 ngx_http_variable_value_t *v, uintptr_t data) |
921 { | 921 { |
922 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | 922 return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data, |
923 &r->headers_in.headers.part, | 923 &r->headers_in.headers.part, |
924 sizeof("http_") - 1); | 924 sizeof("http_") - 1); |
925 } | 925 } |
926 | 926 |
927 | 927 |
928 static ngx_int_t | 928 static ngx_int_t |
929 ngx_http_variable_unknown_header_out(ngx_http_request_t *r, | 929 ngx_http_variable_unknown_header_out(ngx_http_request_t *r, |
930 ngx_http_variable_value_t *v, uintptr_t data) | 930 ngx_http_variable_value_t *v, uintptr_t data) |
931 { | 931 { |
932 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | 932 return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data, |
933 &r->headers_out.headers.part, | 933 &r->headers_out.headers.part, |
934 sizeof("sent_http_") - 1); | 934 sizeof("sent_http_") - 1); |
935 } | 935 } |
936 | 936 |
937 | 937 |
938 static ngx_int_t | 938 static ngx_int_t |
939 ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r, | 939 ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r, |
940 ngx_http_variable_value_t *v, uintptr_t data) | 940 ngx_http_variable_value_t *v, uintptr_t data) |
941 { | 941 { |
942 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | 942 return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data, |
943 &r->headers_out.trailers.part, | 943 &r->headers_out.trailers.part, |
944 sizeof("sent_trailer_") - 1); | 944 sizeof("sent_trailer_") - 1); |
945 } | 945 } |
946 | 946 |
947 | 947 |
948 ngx_int_t | 948 ngx_int_t |
949 ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var, | 949 ngx_http_variable_unknown_header(ngx_http_request_t *r, |
950 ngx_http_variable_value_t *v, ngx_str_t *var, | |
950 ngx_list_part_t *part, size_t prefix) | 951 ngx_list_part_t *part, size_t prefix) |
951 { | 952 { |
952 u_char ch; | 953 u_char *p, ch; |
954 size_t len; | |
953 ngx_uint_t i, n; | 955 ngx_uint_t i, n; |
954 ngx_table_elt_t *header; | 956 ngx_table_elt_t *header, *h, **ph; |
957 | |
958 ph = &h; | |
959 #if (NGX_SUPPRESS_WARN) | |
960 len = 0; | |
961 #endif | |
955 | 962 |
956 header = part->elts; | 963 header = part->elts; |
957 | 964 |
958 for (i = 0; /* void */ ; i++) { | 965 for (i = 0; /* void */ ; i++) { |
959 | 966 |
969 | 976 |
970 if (header[i].hash == 0) { | 977 if (header[i].hash == 0) { |
971 continue; | 978 continue; |
972 } | 979 } |
973 | 980 |
974 for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) { | 981 if (header[i].key.len != var->len - prefix) { |
982 continue; | |
983 } | |
984 | |
985 for (n = 0; n < var->len - prefix; n++) { | |
975 ch = header[i].key.data[n]; | 986 ch = header[i].key.data[n]; |
976 | 987 |
977 if (ch >= 'A' && ch <= 'Z') { | 988 if (ch >= 'A' && ch <= 'Z') { |
978 ch |= 0x20; | 989 ch |= 0x20; |
979 | 990 |
984 if (var->data[n + prefix] != ch) { | 995 if (var->data[n + prefix] != ch) { |
985 break; | 996 break; |
986 } | 997 } |
987 } | 998 } |
988 | 999 |
989 if (n + prefix == var->len && n == header[i].key.len) { | 1000 if (n != var->len - prefix) { |
990 v->len = header[i].value.len; | 1001 continue; |
991 v->valid = 1; | 1002 } |
992 v->no_cacheable = 0; | 1003 |
993 v->not_found = 0; | 1004 len += header[i].value.len + 2; |
994 v->data = header[i].value.data; | 1005 |
995 | 1006 *ph = &header[i]; |
996 return NGX_OK; | 1007 ph = &header[i].next; |
997 } | 1008 } |
998 } | 1009 |
999 | 1010 *ph = NULL; |
1000 v->not_found = 1; | 1011 |
1012 if (h == NULL) { | |
1013 v->not_found = 1; | |
1014 return NGX_OK; | |
1015 } | |
1016 | |
1017 len -= 2; | |
1018 | |
1019 if (h->next == NULL) { | |
1020 | |
1021 v->len = h->value.len; | |
1022 v->valid = 1; | |
1023 v->no_cacheable = 0; | |
1024 v->not_found = 0; | |
1025 v->data = h->value.data; | |
1026 | |
1027 return NGX_OK; | |
1028 } | |
1029 | |
1030 p = ngx_pnalloc(r->pool, len); | |
1031 if (p == NULL) { | |
1032 return NGX_ERROR; | |
1033 } | |
1034 | |
1035 v->len = len; | |
1036 v->valid = 1; | |
1037 v->no_cacheable = 0; | |
1038 v->not_found = 0; | |
1039 v->data = p; | |
1040 | |
1041 for ( ;; ) { | |
1042 | |
1043 p = ngx_copy(p, h->value.data, h->value.len); | |
1044 | |
1045 if (h->next == NULL) { | |
1046 break; | |
1047 } | |
1048 | |
1049 *p++ = ','; *p++ = ' '; | |
1050 | |
1051 h = h->next; | |
1052 } | |
1001 | 1053 |
1002 return NGX_OK; | 1054 return NGX_OK; |
1003 } | 1055 } |
1004 | 1056 |
1005 | 1057 |
1877 return NGX_OK; | 1929 return NGX_OK; |
1878 } | 1930 } |
1879 | 1931 |
1880 ngx_str_set(&name, "sent_http_location"); | 1932 ngx_str_set(&name, "sent_http_location"); |
1881 | 1933 |
1882 return ngx_http_variable_unknown_header(v, &name, | 1934 return ngx_http_variable_unknown_header(r, v, &name, |
1883 &r->headers_out.headers.part, | 1935 &r->headers_out.headers.part, |
1884 sizeof("sent_http_") - 1); | 1936 sizeof("sent_http_") - 1); |
1885 } | 1937 } |
1886 | 1938 |
1887 | 1939 |