diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 7322ff5b4644157995bc241e083e80a7375f4368..9c6dd45206c854adc7941e0412acdae51d445d32 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -34,11 +34,12 @@ #include "src/core/channel/http_server_filter.h" #include <grpc/support/log.h> -typedef struct call_data { - int unused; /* C89 requires at least one struct element */ -} call_data; +typedef struct call_data { int sent_status; } call_data; -typedef struct channel_data { grpc_mdelem *te_trailers; } channel_data; +typedef struct channel_data { + grpc_mdelem *te_trailers; + grpc_mdelem *status_md; +} channel_data; /* used to silence 'variable not used' warnings */ static void ignore_unused(void *ignored) {} @@ -76,6 +77,17 @@ static void call_op(grpc_call_element *elem, grpc_call_op *op) { grpc_call_next_op(elem, op); } break; + case GRPC_SEND_START: + case GRPC_SEND_METADATA: + /* If we haven't sent status 200 yet, we need to so so because it needs to + come before any non : prefixed metadata. */ + if (!calld->sent_status) { + calld->sent_status = 1; + /* status_md is reffed by grpc_call_element_send_metadata */ + grpc_call_element_send_metadata(elem, channeld->status_md); + } + grpc_call_next_op(elem, op); + break; default: /* pass control up or down the stack depending on op->dir */ grpc_call_next_op(elem, op); @@ -109,7 +121,7 @@ static void init_call_elem(grpc_call_element *elem, ignore_unused(channeld); /* initialize members */ - calld->unused = 0; + calld->sent_status = 0; } /* Destructor for call_data */ @@ -137,6 +149,7 @@ static void init_channel_elem(grpc_channel_element *elem, /* initialize members */ channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers"); + channeld->status_md = grpc_mdelem_from_strings(mdctx, ":status", "200"); } /* Destructor for channel data */ @@ -145,6 +158,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) { channel_data *channeld = elem->channel_data; grpc_mdelem_unref(channeld->te_trailers); + grpc_mdelem_unref(channeld->status_md); } const grpc_channel_filter grpc_http_server_filter = { diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 2c859060ebc163044f6e585902a0543cf81127a2..cfff6631f34f337f89fd6613ede30a5dd9791937 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -216,7 +216,6 @@ static void queue_new_rpc(grpc_server *server, call_data *calld, void *tag) { const char *host = NULL; const char *method = NULL; size_t i; - grpc_metadata status_md; for (i = 0; i < count; i++) { if (0 == strcmp(elements[i].key, ":authority")) { @@ -226,11 +225,6 @@ static void queue_new_rpc(grpc_server *server, call_data *calld, void *tag) { } } - status_md.key = ":status"; - status_md.value = "200"; - status_md.value_length = 3; - grpc_call_add_metadata(call, &status_md, GRPC_WRITE_BUFFER_HINT); - grpc_call_internal_ref(call); grpc_cq_end_new_rpc(server->cq, tag, call, grpc_metadata_buffer_cleanup_elements, elements, method,