Mercurial > hg > nginx-quic
comparison src/http/v3/ngx_http_v3_request.c @ 8784:10522e8dea41 quic
HTTP/3: improved processing of multiple Cookie field lines.
As per draft-ietf-quic-http, 4.1.1.2, and similar to HTTP/2 specification,
they ought to be concatenated. This closely follows ngx_http_v2_module.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 30 Dec 2021 12:59:32 +0300 |
parents | de7d36aa9bc7 |
children | f9d7930d0eed |
comparison
equal
deleted
inserted
replaced
8783:de7d36aa9bc7 | 8784:10522e8dea41 |
---|---|
23 ngx_str_t *name, ngx_str_t *value); | 23 ngx_str_t *name, ngx_str_t *value); |
24 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, | 24 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, |
25 ngx_str_t *name, ngx_str_t *value); | 25 ngx_str_t *name, ngx_str_t *value); |
26 static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r); | 26 static ngx_int_t ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r); |
27 static ngx_int_t ngx_http_v3_process_request_header(ngx_http_request_t *r); | 27 static ngx_int_t ngx_http_v3_process_request_header(ngx_http_request_t *r); |
28 static ngx_int_t ngx_http_v3_cookie(ngx_http_request_t *r, ngx_str_t *value); | |
29 static ngx_int_t ngx_http_v3_construct_cookie_header(ngx_http_request_t *r); | |
28 static void ngx_http_v3_read_client_request_body_handler(ngx_http_request_t *r); | 30 static void ngx_http_v3_read_client_request_body_handler(ngx_http_request_t *r); |
29 static ngx_int_t ngx_http_v3_do_read_client_request_body(ngx_http_request_t *r); | 31 static ngx_int_t ngx_http_v3_do_read_client_request_body(ngx_http_request_t *r); |
30 static ngx_int_t ngx_http_v3_request_body_filter(ngx_http_request_t *r, | 32 static ngx_int_t ngx_http_v3_request_body_filter(ngx_http_request_t *r, |
31 ngx_chain_t *in); | 33 ngx_chain_t *in); |
32 | 34 |
599 ngx_table_elt_t *h; | 601 ngx_table_elt_t *h; |
600 ngx_http_header_t *hh; | 602 ngx_http_header_t *hh; |
601 ngx_http_core_srv_conf_t *cscf; | 603 ngx_http_core_srv_conf_t *cscf; |
602 ngx_http_core_main_conf_t *cmcf; | 604 ngx_http_core_main_conf_t *cmcf; |
603 | 605 |
606 static ngx_str_t cookie = ngx_string("cookie"); | |
607 | |
604 len = name->len + value->len; | 608 len = name->len + value->len; |
605 | 609 |
606 if (len > r->v3_parse->header_limit) { | 610 if (len > r->v3_parse->header_limit) { |
607 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | 611 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, |
608 "client sent too large header"); | 612 "client sent too large header"); |
634 | 638 |
635 if (ngx_http_v3_init_pseudo_headers(r) != NGX_OK) { | 639 if (ngx_http_v3_init_pseudo_headers(r) != NGX_OK) { |
636 return NGX_ERROR; | 640 return NGX_ERROR; |
637 } | 641 } |
638 | 642 |
639 h = ngx_list_push(&r->headers_in.headers); | 643 if (name->len == cookie.len |
640 if (h == NULL) { | 644 && ngx_memcmp(name->data, cookie.data, cookie.len) == 0) |
641 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 645 { |
642 return NGX_ERROR; | 646 if (ngx_http_v3_cookie(r, value) != NGX_OK) { |
643 } | 647 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
644 | 648 return NGX_ERROR; |
645 h->key = *name; | 649 } |
646 h->value = *value; | 650 |
647 h->lowcase_key = h->key.data; | 651 } else { |
648 h->hash = ngx_hash_key(h->key.data, h->key.len); | 652 h = ngx_list_push(&r->headers_in.headers); |
649 | 653 if (h == NULL) { |
650 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | 654 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
651 | 655 return NGX_ERROR; |
652 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, | 656 } |
653 h->lowcase_key, h->key.len); | 657 |
654 | 658 h->key = *name; |
655 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | 659 h->value = *value; |
656 return NGX_ERROR; | 660 h->lowcase_key = h->key.data; |
661 h->hash = ngx_hash_key(h->key.data, h->key.len); | |
662 | |
663 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
664 | |
665 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, | |
666 h->lowcase_key, h->key.len); | |
667 | |
668 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | |
669 return NGX_ERROR; | |
670 } | |
657 } | 671 } |
658 | 672 |
659 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 673 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
660 "http3 header: \"%V: %V\"", name, value); | 674 "http3 header: \"%V: %V\"", name, value); |
661 return NGX_OK; | 675 return NGX_OK; |
976 ngx_connection_t *c; | 990 ngx_connection_t *c; |
977 | 991 |
978 c = r->connection; | 992 c = r->connection; |
979 | 993 |
980 if (ngx_http_v3_init_pseudo_headers(r) != NGX_OK) { | 994 if (ngx_http_v3_init_pseudo_headers(r) != NGX_OK) { |
995 return NGX_ERROR; | |
996 } | |
997 | |
998 if (ngx_http_v3_construct_cookie_header(r) != NGX_OK) { | |
981 return NGX_ERROR; | 999 return NGX_ERROR; |
982 } | 1000 } |
983 | 1001 |
984 if (r->headers_in.server.len == 0) { | 1002 if (r->headers_in.server.len == 0) { |
985 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 1003 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
1051 | 1069 |
1052 failed: | 1070 failed: |
1053 | 1071 |
1054 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | 1072 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); |
1055 return NGX_ERROR; | 1073 return NGX_ERROR; |
1074 } | |
1075 | |
1076 | |
1077 static ngx_int_t | |
1078 ngx_http_v3_cookie(ngx_http_request_t *r, ngx_str_t *value) | |
1079 { | |
1080 ngx_str_t *val; | |
1081 ngx_array_t *cookies; | |
1082 | |
1083 cookies = r->v3_parse->cookies; | |
1084 | |
1085 if (cookies == NULL) { | |
1086 cookies = ngx_array_create(r->pool, 2, sizeof(ngx_str_t)); | |
1087 if (cookies == NULL) { | |
1088 return NGX_ERROR; | |
1089 } | |
1090 | |
1091 r->v3_parse->cookies = cookies; | |
1092 } | |
1093 | |
1094 val = ngx_array_push(cookies); | |
1095 if (val == NULL) { | |
1096 return NGX_ERROR; | |
1097 } | |
1098 | |
1099 *val = *value; | |
1100 | |
1101 return NGX_OK; | |
1102 } | |
1103 | |
1104 | |
1105 static ngx_int_t | |
1106 ngx_http_v3_construct_cookie_header(ngx_http_request_t *r) | |
1107 { | |
1108 u_char *buf, *p, *end; | |
1109 size_t len; | |
1110 ngx_str_t *vals; | |
1111 ngx_uint_t i; | |
1112 ngx_array_t *cookies; | |
1113 ngx_table_elt_t *h; | |
1114 ngx_http_header_t *hh; | |
1115 ngx_http_core_main_conf_t *cmcf; | |
1116 | |
1117 static ngx_str_t cookie = ngx_string("cookie"); | |
1118 | |
1119 cookies = r->v3_parse->cookies; | |
1120 | |
1121 if (cookies == NULL) { | |
1122 return NGX_OK; | |
1123 } | |
1124 | |
1125 vals = cookies->elts; | |
1126 | |
1127 i = 0; | |
1128 len = 0; | |
1129 | |
1130 do { | |
1131 len += vals[i].len + 2; | |
1132 } while (++i != cookies->nelts); | |
1133 | |
1134 len -= 2; | |
1135 | |
1136 buf = ngx_pnalloc(r->pool, len + 1); | |
1137 if (buf == NULL) { | |
1138 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1139 return NGX_ERROR; | |
1140 } | |
1141 | |
1142 p = buf; | |
1143 end = buf + len; | |
1144 | |
1145 for (i = 0; /* void */ ; i++) { | |
1146 | |
1147 p = ngx_cpymem(p, vals[i].data, vals[i].len); | |
1148 | |
1149 if (p == end) { | |
1150 *p = '\0'; | |
1151 break; | |
1152 } | |
1153 | |
1154 *p++ = ';'; *p++ = ' '; | |
1155 } | |
1156 | |
1157 h = ngx_list_push(&r->headers_in.headers); | |
1158 if (h == NULL) { | |
1159 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1160 return NGX_ERROR; | |
1161 } | |
1162 | |
1163 h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( | |
1164 ngx_hash('c', 'o'), 'o'), 'k'), 'i'), 'e'); | |
1165 | |
1166 h->key.len = cookie.len; | |
1167 h->key.data = cookie.data; | |
1168 | |
1169 h->value.len = len; | |
1170 h->value.data = buf; | |
1171 | |
1172 h->lowcase_key = cookie.data; | |
1173 | |
1174 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
1175 | |
1176 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, | |
1177 h->lowcase_key, h->key.len); | |
1178 | |
1179 if (hh == NULL) { | |
1180 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1181 return NGX_ERROR; | |
1182 } | |
1183 | |
1184 if (hh->handler(r, h, hh->offset) != NGX_OK) { | |
1185 /* | |
1186 * request has been finalized already | |
1187 * in ngx_http_process_multi_header_lines() | |
1188 */ | |
1189 return NGX_ERROR; | |
1190 } | |
1191 | |
1192 return NGX_OK; | |
1056 } | 1193 } |
1057 | 1194 |
1058 | 1195 |
1059 ngx_int_t | 1196 ngx_int_t |
1060 ngx_http_v3_read_request_body(ngx_http_request_t *r) | 1197 ngx_http_v3_read_request_body(ngx_http_request_t *r) |