From 071599cbcd25cd2669e26d23a6e202e0275f191a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Wed, 3 Jul 2019 17:22:43 +0200 Subject: Add the response_trailers event --- src/gun_default_event_h.erl | 4 ++++ src/gun_event.erl | 11 ++++++++++- src/gun_http.erl | 6 ++++-- src/gun_http2.erl | 11 +++++------ test/event_SUITE.erl | 19 ++++++++++++++++++- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/gun_default_event_h.erl b/src/gun_default_event_h.erl index cd48fc2..ff6f951 100644 --- a/src/gun_default_event_h.erl +++ b/src/gun_default_event_h.erl @@ -24,6 +24,7 @@ -export([response_start/2]). -export([response_inform/2]). -export([response_headers/2]). +-export([response_trailers/2]). -export([response_end/2]). -export([disconnect/2]). -export([terminate/2]). @@ -55,6 +56,9 @@ response_inform(_EventData, State) -> response_headers(_EventData, State) -> State. +response_trailers(_EventData, State) -> + State. + response_end(_EventData, State) -> State. diff --git a/src/gun_event.erl b/src/gun_event.erl index 2a742a1..72abe24 100644 --- a/src/gun_event.erl +++ b/src/gun_event.erl @@ -89,6 +89,16 @@ -callback response_inform(response_headers_event(), State) -> State. -callback response_headers(response_headers_event(), State) -> State. +%% response_trailers. + +-type response_trailers_event() :: #{ + stream_ref := reference(), + reply_to := pid(), + headers := [{binary(), binary()}] +}. + +-callback response_trailers(response_trailers_event(), State) -> State. + %% response_end. -type response_end_event() :: #{ @@ -122,7 +132,6 @@ %% @todo origin_changed %% @todo transport_changed %% @todo protocol_changed -%% @todo response_trailers %% @todo push_promise_start %% @todo push_promise_end %% @todo cancel_start diff --git a/src/gun_http.erl b/src/gun_http.erl index b7c5bc1..4acc3c4 100644 --- a/src/gun_http.erl +++ b/src/gun_http.erl @@ -197,10 +197,12 @@ handle(Data, State=#http_state{in=body_trailer, buffer=Buffer, connection=Conn, {Trailers, Rest} = cow_http:parse_headers(Data2), %% @todo We probably want to pass this to gun_content_handler? ReplyTo ! {gun_trailers, self(), stream_ref(StreamRef), Trailers}, - EvHandlerState = EvHandler:response_end(#{ + ResponseEvent = #{ stream_ref => StreamRef, reply_to => ReplyTo - }, EvHandlerState0), + }, + EvHandlerState1 = EvHandler:response_trailers(ResponseEvent#{headers => Trailers}, EvHandlerState0), + EvHandlerState = EvHandler:response_end(ResponseEvent, EvHandlerState1), case Conn of keepalive -> handle(Rest, end_stream(State#http_state{buffer= <<>>}), EvHandler, EvHandlerState); diff --git a/src/gun_http2.erl b/src/gun_http2.erl index 4814818..a1ba46e 100644 --- a/src/gun_http2.erl +++ b/src/gun_http2.erl @@ -124,10 +124,7 @@ frame(State=#http2_state{http2_machine=HTTP2Machine0}, Frame, EvHandler, EvHandl stream_ref => StreamRef, reply_to => ReplyTo }, EvHandlerState0); - {ok, nofin} -> - %% @todo response_trailers. - EvHandlerState0; - %% This is an invalid headers frame. + %% Trailers or invalid header frame. _ -> EvHandlerState0 end; @@ -259,10 +256,12 @@ trailers_frame(State, StreamID, Trailers, EvHandler, EvHandlerState0) -> #stream{ref=StreamRef, reply_to=ReplyTo} = get_stream_by_id(State, StreamID), %% @todo We probably want to pass this to gun_content_handler? ReplyTo ! {gun_trailers, self(), StreamRef, Trailers}, - EvHandlerState = EvHandler:response_end(#{ + ResponseEvent = #{ stream_ref => StreamRef, reply_to => ReplyTo - }, EvHandlerState0), + }, + EvHandlerState1 = EvHandler:response_trailers(ResponseEvent#{headers => Trailers}, EvHandlerState0), + EvHandlerState = EvHandler:response_end(ResponseEvent, EvHandlerState1), {maybe_delete_stream(State, StreamID, remote, fin), EvHandlerState}. rst_stream_frame(State=#http2_state{streams=Streams0}, StreamID, Reason) -> diff --git a/test/event_SUITE.erl b/test/event_SUITE.erl index 88f67d7..1863f15 100644 --- a/test/event_SUITE.erl +++ b/test/event_SUITE.erl @@ -255,6 +255,19 @@ response_headers(Config) -> } = do_receive_event(?FUNCTION_NAME), gun:close(Pid). +response_trailers(Config) -> + doc("Confirm that the request_trailers event callback is called."), + {ok, Pid, _} = do_gun_open(Config), + {ok, _} = gun:await_up(Pid), + StreamRef = gun:get(Pid, "/trailers", [{<<"te">>, <<"trailers">>}]), + ReplyTo = self(), + #{ + stream_ref := StreamRef, + reply_to := ReplyTo, + headers := [_|_] + } = do_receive_event(?FUNCTION_NAME), + gun:close(Pid). + response_end(Config) -> doc("Confirm that the request_headers event callback is called."), do_response_end(Config, ?FUNCTION_NAME, "/"), @@ -265,7 +278,7 @@ response_end(Config) -> do_response_end(Config, EventName, Path) -> {ok, Pid, _} = do_gun_open(Config), {ok, _} = gun:await_up(Pid), - StreamRef = gun:get(Pid, Path), + StreamRef = gun:get(Pid, Path, [{<<"te">>, <<"trailers">>}]), ReplyTo = self(), #{ stream_ref := StreamRef, @@ -359,6 +372,10 @@ response_headers(EventData, Pid) -> Pid ! {?FUNCTION_NAME, EventData}, Pid. +response_trailers(EventData, Pid) -> + Pid ! {?FUNCTION_NAME, EventData}, + Pid. + response_end(EventData, Pid) -> Pid ! {?FUNCTION_NAME, EventData}, Pid. -- cgit v1.2.3