summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2018-03-17 23:04:25 +0300
committerMaxim Dounin <mdounin@mdounin.ru>2018-03-17 23:04:25 +0300
commit6a0d9e5b2d9274e5ac5059a674763f19c2731b11 (patch)
tree0ac81283fdacc0546598b4f47eae3bd99adfe82c
parent56ad960e7a3d4cf16c03ff231616a76c4834e548 (diff)
downloadnginx-6a0d9e5b2d9274e5ac5059a674763f19c2731b11.tar.gz
gRPC: special handling of the TE request header.
According to the gRPC protocol specification, the "TE" header is used to detect incompatible proxies, and at least grpc-c server rejects requests without "TE: trailers". To preserve the logic, we have to pass "TE: trailers" to the backend if and only if the original request contains "trailers" in the "TE" header. Note that no other TE values are allowed in HTTP/2, so we have to remove anything else.
-rw-r--r--src/http/modules/ngx_http_grpc_module.c69
-rw-r--r--src/http/ngx_http_request.c4
-rw-r--r--src/http/ngx_http_request.h1
3 files changed, 72 insertions, 2 deletions
diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c
index fcf5e20cb..774f8c79b 100644
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -176,6 +176,10 @@ static void ngx_http_grpc_abort_request(ngx_http_request_t *r);
static void ngx_http_grpc_finalize_request(ngx_http_request_t *r,
ngx_int_t rc);
+static ngx_int_t ngx_http_grpc_internal_trailers_variable(
+ ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
+
+static ngx_int_t ngx_http_grpc_add_variables(ngx_conf_t *cf);
static void *ngx_http_grpc_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -419,7 +423,7 @@ static ngx_command_t ngx_http_grpc_commands[] = {
static ngx_http_module_t ngx_http_grpc_module_ctx = {
- NULL, /* preconfiguration */
+ ngx_http_grpc_add_variables, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
@@ -463,10 +467,10 @@ static u_char ngx_http_grpc_connection_start[] =
static ngx_keyval_t ngx_http_grpc_headers[] = {
{ ngx_string("Content-Length"), ngx_string("$content_length") },
+ { ngx_string("TE"), ngx_string("$grpc_internal_trailers") },
{ ngx_string("Host"), ngx_string("") },
{ ngx_string("Connection"), ngx_string("") },
{ ngx_string("Transfer-Encoding"), ngx_string("") },
- { ngx_string("TE"), ngx_string("") },
{ ngx_string("Keep-Alive"), ngx_string("") },
{ ngx_string("Expect"), ngx_string("") },
{ ngx_string("Upgrade"), ngx_string("") },
@@ -486,6 +490,16 @@ static ngx_str_t ngx_http_grpc_hide_headers[] = {
};
+static ngx_http_variable_t ngx_http_grpc_vars[] = {
+
+ { ngx_string("grpc_internal_trailers"), NULL,
+ ngx_http_grpc_internal_trailers_variable, 0,
+ NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
+
+ ngx_http_null_variable
+};
+
+
static ngx_int_t
ngx_http_grpc_handler(ngx_http_request_t *r)
{
@@ -3996,6 +4010,57 @@ ngx_http_grpc_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
}
+static ngx_int_t
+ngx_http_grpc_internal_trailers_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_table_elt_t *te;
+
+ te = r->headers_in.te;
+
+ if (te == NULL) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ if (ngx_strlcasestrn(te->value.data, te->value.data + te->value.len,
+ (u_char *) "trailers", 8 - 1)
+ == NULL)
+ {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+
+ v->data = (u_char *) "trailers";
+ v->len = sizeof("trailers") - 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_grpc_add_variables(ngx_conf_t *cf)
+{
+ ngx_http_variable_t *var, *v;
+
+ for (v = ngx_http_grpc_vars; v->name.len; v++) {
+ var = ngx_http_add_variable(cf, &v->name, v->flags);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->get_handler = v->get_handler;
+ var->data = v->data;
+ }
+
+ return NGX_OK;
+}
+
+
static void *
ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
{
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 89cfe77ad..2db7a6279 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -132,6 +132,10 @@ ngx_http_header_t ngx_http_headers_in[] = {
offsetof(ngx_http_headers_in_t, transfer_encoding),
ngx_http_process_header_line },
+ { ngx_string("TE"),
+ offsetof(ngx_http_headers_in_t, te),
+ ngx_http_process_header_line },
+
{ ngx_string("Expect"),
offsetof(ngx_http_headers_in_t, expect),
ngx_http_process_unique_header_line },
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 5d44c06ef..39baa0f0c 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -197,6 +197,7 @@ typedef struct {
ngx_table_elt_t *if_range;
ngx_table_elt_t *transfer_encoding;
+ ngx_table_elt_t *te;
ngx_table_elt_t *expect;
ngx_table_elt_t *upgrade;