Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_grpc_module.c @ 7983:39501ce97e29
gRPC: generate error when response size is wrong.
As long as the "Content-Length" header is given, we now make sure
it exactly matches the size of the response. If it doesn't,
the response is considered malformed and must not be forwarded
(https://tools.ietf.org/html/rfc7540#section-8.1.2.6). While it
is not really possible to "not forward" the response which is already
being forwarded, we generate an error instead, which is the closest
equivalent.
Previous behaviour was to pass everything to the client, but this
seems to be suboptimal and causes issues (ticket #1695). Also this
directly contradicts HTTP/2 specification requirements.
Note that the new behaviour for the gRPC proxy is more strict than that
applied in other variants of proxying. This is intentional, as HTTP/2
specification requires us to do so, while in other types of proxying
malformed responses from backends are well known and historically
tolerated.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 06 Jul 2020 18:36:25 +0300 |
parents | 716eddd74bc2 |
children | 485dba3e2a01 |
comparison
equal
deleted
inserted
replaced
7982:05e42236e95b | 7983:39501ce97e29 |
---|---|
81 | 81 |
82 ngx_uint_t id; | 82 ngx_uint_t id; |
83 | 83 |
84 ngx_uint_t pings; | 84 ngx_uint_t pings; |
85 ngx_uint_t settings; | 85 ngx_uint_t settings; |
86 | |
87 off_t length; | |
86 | 88 |
87 ssize_t send_window; | 89 ssize_t send_window; |
88 size_t recv_window; | 90 size_t recv_window; |
89 | 91 |
90 size_t rest; | 92 size_t rest; |
1951 ngx_http_upstream_t *u; | 1953 ngx_http_upstream_t *u; |
1952 | 1954 |
1953 r = ctx->request; | 1955 r = ctx->request; |
1954 u = r->upstream; | 1956 u = r->upstream; |
1955 | 1957 |
1956 u->length = 1; | 1958 if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT |
1959 || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED | |
1960 || r->method == NGX_HTTP_HEAD) | |
1961 { | |
1962 ctx->length = 0; | |
1963 | |
1964 } else { | |
1965 ctx->length = u->headers_in.content_length_n; | |
1966 } | |
1957 | 1967 |
1958 if (ctx->end_stream) { | 1968 if (ctx->end_stream) { |
1969 | |
1970 if (ctx->length > 0) { | |
1971 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1972 "upstream prematurely closed stream"); | |
1973 return NGX_ERROR; | |
1974 } | |
1975 | |
1959 u->length = 0; | 1976 u->length = 0; |
1977 | |
1978 } else { | |
1979 u->length = 1; | |
1960 } | 1980 } |
1961 | 1981 |
1962 return NGX_OK; | 1982 return NGX_OK; |
1963 } | 1983 } |
1964 | 1984 |
1996 rc = ngx_http_grpc_parse_frame(r, ctx, b); | 2016 rc = ngx_http_grpc_parse_frame(r, ctx, b); |
1997 | 2017 |
1998 if (rc == NGX_AGAIN) { | 2018 if (rc == NGX_AGAIN) { |
1999 | 2019 |
2000 if (ctx->done) { | 2020 if (ctx->done) { |
2021 | |
2022 if (ctx->length > 0) { | |
2023 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
2024 "upstream prematurely closed stream"); | |
2025 return NGX_ERROR; | |
2026 } | |
2001 | 2027 |
2002 /* | 2028 /* |
2003 * We have finished parsing the response and the | 2029 * We have finished parsing the response and the |
2004 * remaining control frames. If there are unsent | 2030 * remaining control frames. If there are unsent |
2005 * control frames, post a write event to send them. | 2031 * control frames, post a write event to send them. |
2048 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 2074 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
2049 "upstream sent data frame " | 2075 "upstream sent data frame " |
2050 "for unknown stream %ui", | 2076 "for unknown stream %ui", |
2051 ctx->stream_id); | 2077 ctx->stream_id); |
2052 return NGX_ERROR; | 2078 return NGX_ERROR; |
2079 } | |
2080 | |
2081 if (ctx->length != -1) { | |
2082 if ((off_t) ctx->rest > ctx->length) { | |
2083 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
2084 "upstream sent response body larger " | |
2085 "than indicated content length"); | |
2086 return NGX_ERROR; | |
2087 } | |
2088 | |
2089 ctx->length -= ctx->rest; | |
2053 } | 2090 } |
2054 | 2091 |
2055 if (ctx->rest > ctx->recv_window) { | 2092 if (ctx->rest > ctx->recv_window) { |
2056 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 2093 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
2057 "upstream violated stream flow control, " | 2094 "upstream violated stream flow control, " |