Klaus Demo nginx / 6559a42
gRPC: special handling of "trailer only" responses. The gRPC protocol makes a distinction between HEADERS frame with the END_STREAM flag set, and a HEADERS frame followed by an empty DATA frame with the END_STREAM flag. The latter is not permitted, and results in errors not being propagated through nginx. Instead, gRPC clients complain that "server closed the stream without sending trailers" (seen in grpc-go) or "13: Received RST_STREAM with error code 2" (seen in grpc-c). To fix this, nginx now returns HEADERS with the END_STREAM flag if the response length is known to be 0, and we are not expecting any trailer headers to be added. And the response length is explicitly set to 0 in the gRPC proxy if we see initial HEADERS frame with the END_STREAM flag set. Maxim Dounin 2 years ago
2 changed file(s) with 16 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
17421742 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
17431743 "grpc header done");
17441744
1745 if (ctx->end_stream
1746 && ctx->in == NULL
1747 && ctx->out == NULL
1748 && ctx->output_closed
1749 && b->last == b->pos)
1750 {
1751 u->keepalive = 1;
1745 if (ctx->end_stream) {
1746 u->headers_in.content_length_n = 0;
1747
1748 if (ctx->in == NULL
1749 && ctx->out == NULL
1750 && ctx->output_closed
1751 && b->last == b->pos)
1752 {
1753 u->keepalive = 1;
1754 }
17521755 }
17531756
17541757 return NGX_OK;
135135 u_char status, *pos, *start, *p, *tmp;
136136 size_t len, tmp_len;
137137 ngx_str_t host, location;
138 ngx_uint_t i, port;
138 ngx_uint_t i, port, fin;
139139 ngx_list_part_t *part;
140140 ngx_table_elt_t *header;
141141 ngx_connection_t *fc;
642642 header[i].value.len, tmp);
643643 }
644644
645 frame = ngx_http_v2_create_headers_frame(r, start, pos, r->header_only);
645 fin = r->header_only
646 || (r->headers_out.content_length_n == 0 && !r->expect_trailers);
647
648 frame = ngx_http_v2_create_headers_frame(r, start, pos, fin);
646649 if (frame == NULL) {
647650 return NGX_ERROR;
648651 }
14361439 in = in->next;
14371440 }
14381441
1439 if (in == NULL) {
1442 if (in == NULL || stream->out_closed) {
14401443
14411444 if (stream->queued) {
14421445 fc->write->active = 1;