comparison src/http/v3/ngx_http_v3_filter_module.c @ 8624:3fdf0afd5d45 quic

HTTP/3: fixed pushed request finalization in case of error. Previously request could be finalized twice. For example, this could happen if "Host" header was invalid.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 17 Sep 2021 15:28:31 +0300
parents 6a383020d61e
children 33578b8d453d
comparison
equal deleted inserted replaced
8623:630ecd703805 8624:3fdf0afd5d45
878 878
879 static ngx_int_t 879 static ngx_int_t
880 ngx_http_v3_create_push_request(ngx_http_request_t *pr, ngx_str_t *path, 880 ngx_http_v3_create_push_request(ngx_http_request_t *pr, ngx_str_t *path,
881 uint64_t push_id) 881 uint64_t push_id)
882 { 882 {
883 ngx_pool_t *pool;
884 ngx_connection_t *c, *pc; 883 ngx_connection_t *c, *pc;
885 ngx_http_request_t *r; 884 ngx_http_request_t *r;
886 ngx_http_log_ctx_t *ctx; 885 ngx_http_log_ctx_t *ctx;
887 ngx_http_connection_t *hc, *phc; 886 ngx_http_connection_t *hc, *phc;
888 ngx_http_core_srv_conf_t *cscf; 887 ngx_http_core_srv_conf_t *cscf;
889 888
890 pc = pr->connection; 889 pc = pr->connection;
891 890
892 r = NULL;
893
894 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, 891 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
895 "http3 create push request id:%uL", push_id); 892 "http3 create push request id:%uL", push_id);
896 893
897 c = ngx_http_v3_create_push_stream(pc, push_id); 894 c = ngx_http_v3_create_push_stream(pc, push_id);
898 if (c == NULL) { 895 if (c == NULL) {
899 return NGX_ABORT; 896 return NGX_ABORT;
900 } 897 }
901 898
902 hc = ngx_palloc(c->pool, sizeof(ngx_http_connection_t)); 899 hc = ngx_palloc(c->pool, sizeof(ngx_http_connection_t));
903 if (hc == NULL) { 900 if (hc == NULL) {
904 goto failed; 901 ngx_http_close_connection(c);
902 return NGX_ERROR;
905 } 903 }
906 904
907 phc = ngx_http_quic_get_connection(pc); 905 phc = ngx_http_quic_get_connection(pc);
908 ngx_memcpy(hc, phc, sizeof(ngx_http_connection_t)); 906 ngx_memcpy(hc, phc, sizeof(ngx_http_connection_t));
909 c->data = hc; 907 c->data = hc;
910 908
911 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); 909 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
912 if (ctx == NULL) { 910 if (ctx == NULL) {
913 goto failed; 911 ngx_http_close_connection(c);
912 return NGX_ERROR;
914 } 913 }
915 914
916 ctx->connection = c; 915 ctx->connection = c;
917 ctx->request = NULL; 916 ctx->request = NULL;
918 ctx->current_request = NULL; 917 ctx->current_request = NULL;
923 922
924 c->log_error = NGX_ERROR_INFO; 923 c->log_error = NGX_ERROR_INFO;
925 924
926 r = ngx_http_create_request(c); 925 r = ngx_http_create_request(c);
927 if (r == NULL) { 926 if (r == NULL) {
928 goto failed; 927 ngx_http_close_connection(c);
928 return NGX_ERROR;
929 } 929 }
930 930
931 c->data = r; 931 c->data = r;
932 932
933 ngx_str_set(&r->http_protocol, "HTTP/3.0"); 933 ngx_str_set(&r->http_protocol, "HTTP/3.0");
939 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); 939 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
940 940
941 r->header_in = ngx_create_temp_buf(r->pool, 941 r->header_in = ngx_create_temp_buf(r->pool,
942 cscf->client_header_buffer_size); 942 cscf->client_header_buffer_size);
943 if (r->header_in == NULL) { 943 if (r->header_in == NULL) {
944 goto failed; 944 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
945 return NGX_ERROR;
945 } 946 }
946 947
947 if (ngx_list_init(&r->headers_in.headers, r->pool, 4, 948 if (ngx_list_init(&r->headers_in.headers, r->pool, 4,
948 sizeof(ngx_table_elt_t)) 949 sizeof(ngx_table_elt_t))
949 != NGX_OK) 950 != NGX_OK)
950 { 951 {
951 goto failed; 952 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
953 return NGX_ERROR;
952 } 954 }
953 955
954 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; 956 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
955 957
956 r->schema.data = ngx_pstrdup(r->pool, &pr->schema); 958 r->schema.data = ngx_pstrdup(r->pool, &pr->schema);
957 if (r->schema.data == NULL) { 959 if (r->schema.data == NULL) {
958 goto failed; 960 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
961 return NGX_ERROR;
959 } 962 }
960 963
961 r->schema.len = pr->schema.len; 964 r->schema.len = pr->schema.len;
962 965
963 r->uri_start = ngx_pstrdup(r->pool, path); 966 r->uri_start = ngx_pstrdup(r->pool, path);
964 if (r->uri_start == NULL) { 967 if (r->uri_start == NULL) {
965 goto failed; 968 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
969 return NGX_ERROR;
966 } 970 }
967 971
968 r->uri_end = r->uri_start + path->len; 972 r->uri_end = r->uri_start + path->len;
969 973
970 if (ngx_http_parse_uri(r) != NGX_OK) { 974 if (ngx_http_parse_uri(r) != NGX_OK) {
971 goto failed; 975 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
976 return NGX_ERROR;
972 } 977 }
973 978
974 if (ngx_http_process_request_uri(r) != NGX_OK) { 979 if (ngx_http_process_request_uri(r) != NGX_OK) {
975 goto failed; 980 return NGX_ERROR;
976 } 981 }
977 982
978 if (ngx_http_v3_set_push_header(r, "host", &pr->headers_in.server) 983 if (ngx_http_v3_set_push_header(r, "host", &pr->headers_in.server)
979 != NGX_OK) 984 != NGX_OK)
980 { 985 {
981 goto failed; 986 return NGX_ERROR;
982 } 987 }
983 988
984 if (pr->headers_in.accept_encoding) { 989 if (pr->headers_in.accept_encoding) {
985 if (ngx_http_v3_set_push_header(r, "accept-encoding", 990 if (ngx_http_v3_set_push_header(r, "accept-encoding",
986 &pr->headers_in.accept_encoding->value) 991 &pr->headers_in.accept_encoding->value)
987 != NGX_OK) 992 != NGX_OK)
988 { 993 {
989 goto failed; 994 return NGX_ERROR;
990 } 995 }
991 } 996 }
992 997
993 if (pr->headers_in.accept_language) { 998 if (pr->headers_in.accept_language) {
994 if (ngx_http_v3_set_push_header(r, "accept-language", 999 if (ngx_http_v3_set_push_header(r, "accept-language",
995 &pr->headers_in.accept_language->value) 1000 &pr->headers_in.accept_language->value)
996 != NGX_OK) 1001 != NGX_OK)
997 { 1002 {
998 goto failed; 1003 return NGX_ERROR;
999 } 1004 }
1000 } 1005 }
1001 1006
1002 if (pr->headers_in.user_agent) { 1007 if (pr->headers_in.user_agent) {
1003 if (ngx_http_v3_set_push_header(r, "user-agent", 1008 if (ngx_http_v3_set_push_header(r, "user-agent",
1004 &pr->headers_in.user_agent->value) 1009 &pr->headers_in.user_agent->value)
1005 != NGX_OK) 1010 != NGX_OK)
1006 { 1011 {
1007 goto failed; 1012 return NGX_ERROR;
1008 } 1013 }
1009 } 1014 }
1010 1015
1011 c->read->handler = ngx_http_v3_push_request_handler; 1016 c->read->handler = ngx_http_v3_push_request_handler;
1012 c->read->handler = ngx_http_v3_push_request_handler; 1017 c->read->handler = ngx_http_v3_push_request_handler;
1013 1018
1014 ngx_post_event(c->read, &ngx_posted_events); 1019 ngx_post_event(c->read, &ngx_posted_events);
1015 1020
1016 return NGX_OK; 1021 return NGX_OK;
1017
1018 failed:
1019
1020 if (r) {
1021 ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1022 }
1023
1024 c->destroyed = 1;
1025
1026 pool = c->pool;
1027
1028 ngx_close_connection(c);
1029
1030 ngx_destroy_pool(pool);
1031
1032 return NGX_ERROR;
1033 } 1022 }
1034 1023
1035 1024
1036 static ngx_int_t 1025 static ngx_int_t
1037 ngx_http_v3_set_push_header(ngx_http_request_t *r, const char *name, 1026 ngx_http_v3_set_push_header(ngx_http_request_t *r, const char *name,
1047 1036
1048 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 1037 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1049 1038
1050 p = ngx_pnalloc(r->pool, value->len + 1); 1039 p = ngx_pnalloc(r->pool, value->len + 1);
1051 if (p == NULL) { 1040 if (p == NULL) {
1041 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1052 return NGX_ERROR; 1042 return NGX_ERROR;
1053 } 1043 }
1054 1044
1055 ngx_memcpy(p, value->data, value->len); 1045 ngx_memcpy(p, value->data, value->len);
1056 p[value->len] = '\0'; 1046 p[value->len] = '\0';
1057 1047
1058 h = ngx_list_push(&r->headers_in.headers); 1048 h = ngx_list_push(&r->headers_in.headers);
1059 if (h == NULL) { 1049 if (h == NULL) {
1050 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1060 return NGX_ERROR; 1051 return NGX_ERROR;
1061 } 1052 }
1062 1053
1063 h->key.data = (u_char *) name; 1054 h->key.data = (u_char *) name;
1064 h->key.len = ngx_strlen(name); 1055 h->key.len = ngx_strlen(name);