From d2d0a1184e15c6497b11c4248b335573dd87d459 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 19 Jan 2015 16:07:52 -0800 Subject: [PATCH] Capture :path, and send it separately --- src/core/channel/channel_stack.c | 11 ++++++++++ src/core/channel/channel_stack.h | 2 ++ src/core/channel/http_server_filter.c | 30 +++++++++++++++++++++------ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c index 5ee412bf7d0..1320568d23d 100644 --- a/src/core/channel/channel_stack.c +++ b/src/core/channel/channel_stack.c @@ -202,6 +202,17 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) { static void do_nothing(void *user_data, grpc_op_error error) {} +void grpc_call_element_recv_metadata(grpc_call_element *cur_elem, + grpc_mdelem *mdelem) { + grpc_call_op metadata_op; + metadata_op.type = GRPC_RECV_METADATA; + metadata_op.dir = GRPC_CALL_UP; + metadata_op.done_cb = do_nothing; + metadata_op.user_data = NULL; + metadata_op.data.metadata = grpc_mdelem_ref(mdelem); + grpc_call_next_op(cur_elem, &metadata_op); +} + void grpc_call_element_send_metadata(grpc_call_element *cur_elem, grpc_mdelem *mdelem) { grpc_call_op metadata_op; diff --git a/src/core/channel/channel_stack.h b/src/core/channel/channel_stack.h index eb68102b435..8d3ed0aeede 100644 --- a/src/core/channel/channel_stack.h +++ b/src/core/channel/channel_stack.h @@ -292,6 +292,8 @@ void grpc_call_log_op(char *file, int line, gpr_log_severity severity, void grpc_call_element_send_metadata(grpc_call_element *cur_elem, grpc_mdelem *elem); +void grpc_call_element_recv_metadata(grpc_call_element *cur_elem, + grpc_mdelem *elem); void grpc_call_element_send_cancel(grpc_call_element *cur_elem); #ifdef GRPC_CHANNEL_STACK_TRACE diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 19b9606b433..8290ead8a78 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -37,10 +37,11 @@ #include typedef struct call_data { - int sent_status; - int seen_scheme; - int seen_method; - int seen_te_trailers; + gpr_uint8 sent_status; + gpr_uint8 seen_scheme; + gpr_uint8 seen_method; + gpr_uint8 seen_te_trailers; + grpc_mdelem *path; } call_data; typedef struct channel_data { @@ -52,6 +53,7 @@ typedef struct channel_data { grpc_mdelem *grpc_scheme; grpc_mdelem *content_type; grpc_mdelem *status; + grpc_mdstr *path_key; } channel_data; /* used to silence 'variable not used' warnings */ @@ -120,6 +122,13 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_mdelem_unref(op->data.metadata); op->done_cb(op->user_data, GRPC_OP_OK); grpc_call_element_send_cancel(elem); + } else if (op->data.metadata->key == channeld->path_key) { + if (calld->path != NULL) { + gpr_log(GPR_ERROR, "Received :path twice"); + grpc_mdelem_unref(calld->path); + } + calld->path = grpc_mdelem_ref(op->data.metadata); + op->done_cb(op->user_data, GRPC_OP_OK); } else { /* pass the event up */ grpc_call_next_op(elem, op); @@ -129,7 +138,10 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, /* Have we seen the required http2 transport headers? (:method, :scheme, content-type, with :path and :authority covered at the channel level right now) */ - if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers) { + if (calld->seen_method && calld->seen_scheme && calld->seen_te_trailers && + calld->path) { + grpc_call_element_recv_metadata(elem, calld->path); + calld->path = NULL; grpc_call_next_op(elem, op); } else { if (!calld->seen_method) { @@ -189,6 +201,7 @@ static void init_call_elem(grpc_call_element *elem, ignore_unused(channeld); /* initialize members */ + calld->path = NULL; calld->sent_status = 0; calld->seen_scheme = 0; calld->seen_method = 0; @@ -201,8 +214,11 @@ static void destroy_call_elem(grpc_call_element *elem) { call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; - ignore_unused(calld); ignore_unused(channeld); + + if (calld->path) { + grpc_mdelem_unref(calld->path); + } } /* Constructor for channel_data */ @@ -225,6 +241,7 @@ static void init_channel_elem(grpc_channel_element *elem, channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http"); channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https"); channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc"); + channeld->path_key = grpc_mdstr_from_string(mdctx, ":path"); channeld->content_type = grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc"); } @@ -241,6 +258,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) { grpc_mdelem_unref(channeld->https_scheme); grpc_mdelem_unref(channeld->grpc_scheme); grpc_mdelem_unref(channeld->content_type); + grpc_mdstr_unref(channeld->path_key); } const grpc_channel_filter grpc_http_server_filter = {