Drop legacy headers support (#144)

This commit is contained in:
Andrew Mayorov 2020-08-11 13:49:06 +03:00 committed by GitHub
parent 33b6991373
commit 42dbb91b2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 242 deletions

View File

@ -42,7 +42,7 @@
-define(ERROR_RESP_BODY , <<"parse http response body error">> ). -define(ERROR_RESP_BODY , <<"parse http response body error">> ).
-define(ERROR_RESP_HEADER , <<"parse http response headers error">>). -define(ERROR_RESP_HEADER , <<"parse http response headers error">>).
-define(BAD_RESP_HEADER(Mode) , <<"reason unknown due to bad ", ?HEADER_PREFIX(Mode)/binary, "-error- headers">>). -define(BAD_RESP_HEADER , <<"reason unknown due to bad ", ?HEADER_PREFIX/binary, "-error- headers">>).
%% %%
%% API %% API
@ -196,16 +196,14 @@ close(Transport) ->
-spec handle_result(_, woody_state:st()) -> -spec handle_result(_, woody_state:st()) ->
{ok, woody:http_body()} | error(). {ok, woody:http_body()} | error().
handle_result({ok, 200, Headers, Ref}, WoodyState) -> handle_result({ok, 200, Headers, Ref}, WoodyState) ->
Mode = woody_util:get_error_headers_mode(Headers), Meta = case check_error_reason(Headers, 200, WoodyState) of
Meta = case check_error_reason(Headers, 200, Mode, WoodyState) of
<<>> -> #{}; <<>> -> #{};
Reason -> #{reason => Reason} Reason -> #{reason => Reason}
end, end,
_ = log_event(?EV_CLIENT_RECEIVE, WoodyState, Meta#{status => ok, code => 200}), _ = log_event(?EV_CLIENT_RECEIVE, WoodyState, Meta#{status => ok, code => 200}),
get_body(hackney:body(Ref), WoodyState); get_body(hackney:body(Ref), WoodyState);
handle_result({ok, Code, Headers, Ref}, WoodyState) -> handle_result({ok, Code, Headers, Ref}, WoodyState) ->
Mode = woody_util:get_error_headers_mode(Headers), {Class, Details} = check_error_headers(Code, Headers, WoodyState),
{Class, Details} = check_error_headers(Code, Headers, Mode, WoodyState),
_ = log_event(?EV_CLIENT_RECEIVE, WoodyState, #{status=>error, code=>Code, reason=>Details}), _ = log_event(?EV_CLIENT_RECEIVE, WoodyState, #{status=>error, code=>Code, reason=>Details}),
%% Free the connection %% Free the connection
case hackney:skip_body(Ref) of case hackney:skip_body(Ref) of
@ -259,12 +257,12 @@ get_body({error, Reason}, WoodyState) ->
_ = log_internal_error(?ERROR_RESP_BODY, Reason, WoodyState), _ = log_internal_error(?ERROR_RESP_BODY, Reason, WoodyState),
{error, {system, {internal, result_unknown, ?ERROR_RESP_BODY}}}. {error, {system, {internal, result_unknown, ?ERROR_RESP_BODY}}}.
-spec check_error_headers(woody:http_code(), woody:http_headers(), woody_util:headers_mode(), woody_state:st()) -> -spec check_error_headers(woody:http_code(), woody:http_headers(), woody_state:st()) ->
{woody_error:class(), woody_error:details()}. {woody_error:class(), woody_error:details()}.
check_error_headers(502, Headers, Mode, WoodyState) -> check_error_headers(502, Headers, WoodyState) ->
check_502_error_class(get_error_class_header_value(Headers, Mode), Headers, Mode, WoodyState); check_502_error_class(get_error_class_header_value(Headers), Headers, WoodyState);
check_error_headers(Code, Headers, Mode, WoodyState) -> check_error_headers(Code, Headers, WoodyState) ->
{get_error_class(Code), check_error_reason(Headers, Code, Mode, WoodyState)}. {get_error_class(Code), check_error_reason(Headers, Code, WoodyState)}.
-spec get_error_class(woody:http_code()) -> -spec get_error_class(woody:http_code()) ->
woody_error:class(). woody_error:class().
@ -275,40 +273,40 @@ get_error_class(504) ->
get_error_class(_) -> get_error_class(_) ->
result_unexpected. result_unexpected.
-spec check_502_error_class(header_parse_value(), woody:http_headers(), woody_util:headers_mode(), woody_state:st()) -> -spec check_502_error_class(header_parse_value(), woody:http_headers(), woody_state:st()) ->
{woody_error:class(), woody_error:details()}. {woody_error:class(), woody_error:details()}.
check_502_error_class(none, Headers, Mode, WoodyState) -> check_502_error_class(none, Headers, WoodyState) ->
_ = log_event(?EV_TRACE, WoodyState, #{event => woody_util:to_binary([?HEADER_E_CLASS(Mode), " header missing"])}), _ = log_event(?EV_TRACE, WoodyState, #{event => woody_util:to_binary([?HEADER_E_CLASS, " header missing"])}),
{result_unexpected, check_error_reason(Headers, 502, Mode, WoodyState)}; {result_unexpected, check_error_reason(Headers, 502, WoodyState)};
check_502_error_class(<<"result unexpected">>, Headers, Mode, WoodyState) -> check_502_error_class(<<"result unexpected">>, Headers, WoodyState) ->
{result_unexpected, check_error_reason(Headers, 502, Mode, WoodyState)}; {result_unexpected, check_error_reason(Headers, 502, WoodyState)};
check_502_error_class(<<"resource unavailable">>, Headers, Mode, WoodyState) -> check_502_error_class(<<"resource unavailable">>, Headers, WoodyState) ->
{resource_unavailable, check_error_reason(Headers, 502, Mode, WoodyState)}; {resource_unavailable, check_error_reason(Headers, 502, WoodyState)};
check_502_error_class(<<"result unknown">>, Headers, Mode, WoodyState) -> check_502_error_class(<<"result unknown">>, Headers, WoodyState) ->
{result_unknown, check_error_reason(Headers, 502, Mode, WoodyState)}; {result_unknown, check_error_reason(Headers, 502, WoodyState)};
check_502_error_class(Bad, _, Mode, WoodyState) -> check_502_error_class(Bad, _, WoodyState) ->
_ = log_internal_error(?ERROR_RESP_HEADER, ["unknown ", ?HEADER_E_CLASS(Mode), " header value: ", Bad], WoodyState), _ = log_internal_error(?ERROR_RESP_HEADER, ["unknown ", ?HEADER_E_CLASS, " header value: ", Bad], WoodyState),
{result_unexpected, ?BAD_RESP_HEADER(Mode)}. {result_unexpected, ?BAD_RESP_HEADER}.
-spec check_error_reason(woody:http_headers(), woody:http_code(), woody_util:headers_mode(), woody_state:st()) -> -spec check_error_reason(woody:http_headers(), woody:http_code(), woody_state:st()) ->
woody_error:details(). woody_error:details().
check_error_reason(Headers, Code, Mode, WoodyState) -> check_error_reason(Headers, Code, WoodyState) ->
do_check_error_reason(get_header_value(?HEADER_E_REASON(Mode), Headers), Code, Mode, WoodyState). do_check_error_reason(get_header_value(?HEADER_E_REASON, Headers), Code, WoodyState).
-spec do_check_error_reason(header_parse_value(), woody:http_code(), woody_util:headers_mode(), woody_state:st()) -> -spec do_check_error_reason(header_parse_value(), woody:http_code(), woody_state:st()) ->
woody_error:details(). woody_error:details().
do_check_error_reason(none, 200, _Mode, _WoodyState) -> do_check_error_reason(none, 200, _WoodyState) ->
<<>>; <<>>;
do_check_error_reason(none, Code, Mode, WoodyState) -> do_check_error_reason(none, Code, WoodyState) ->
_ = log_event(?EV_TRACE, WoodyState, #{event => woody_util:to_binary([?HEADER_E_REASON(Mode), " header missing"])}), _ = log_event(?EV_TRACE, WoodyState, #{event => woody_util:to_binary([?HEADER_E_REASON, " header missing"])}),
woody_util:to_binary(["got response with http code ", Code, " and without ", ?HEADER_E_REASON(Mode), " header"]); woody_util:to_binary(["got response with http code ", Code, " and without ", ?HEADER_E_REASON, " header"]);
do_check_error_reason(Reason, _, _, _) -> do_check_error_reason(Reason, _, _) ->
Reason. Reason.
-spec get_error_class_header_value(woody:http_headers(), woody_util:headers_mode()) -> -spec get_error_class_header_value(woody:http_headers()) ->
header_parse_value(). header_parse_value().
get_error_class_header_value(Headers, Mode) -> get_error_class_header_value(Headers) ->
case get_header_value(?HEADER_E_CLASS(Mode), Headers) of case get_header_value(?HEADER_E_CLASS, Headers) of
None when None =:= none orelse None =:= multiple -> None when None =:= none orelse None =:= multiple ->
None; None;
Value -> Value ->
@ -329,14 +327,11 @@ get_header_value(Name, Headers) ->
woody:http_headers(). woody:http_headers().
make_woody_headers(Context) -> make_woody_headers(Context) ->
add_optional_headers(Context, #{ add_optional_headers(Context, #{
<<"content-type">> => ?CONTENT_TYPE_THRIFT, <<"content-type">> => ?CONTENT_TYPE_THRIFT,
<<"accept">> => ?CONTENT_TYPE_THRIFT, <<"accept">> => ?CONTENT_TYPE_THRIFT,
?NORMAL_HEADER_RPC_ROOT_ID => woody_context:get_rpc_id(trace_id , Context), ?HEADER_RPC_ROOT_ID => woody_context:get_rpc_id(trace_id , Context),
?NORMAL_HEADER_RPC_ID => woody_context:get_rpc_id(span_id , Context), ?HEADER_RPC_ID => woody_context:get_rpc_id(span_id , Context),
?NORMAL_HEADER_RPC_PARENT_ID => woody_context:get_rpc_id(parent_id, Context), ?HEADER_RPC_PARENT_ID => woody_context:get_rpc_id(parent_id, Context)
?LEGACY_HEADER_RPC_ROOT_ID => woody_context:get_rpc_id(trace_id , Context),
?LEGACY_HEADER_RPC_ID => woody_context:get_rpc_id(span_id , Context),
?LEGACY_HEADER_RPC_PARENT_ID => woody_context:get_rpc_id(parent_id, Context)
}). }).
-spec add_optional_headers(woody_context:ctx(), woody:http_headers()) -> -spec add_optional_headers(woody_context:ctx(), woody:http_headers()) ->
@ -352,10 +347,7 @@ add_metadata_headers(Context, Headers) ->
-spec add_metadata_header(woody:http_header_name(), woody:http_header_val(), woody:http_headers()) -> -spec add_metadata_header(woody:http_header_name(), woody:http_header_val(), woody:http_headers()) ->
woody:http_headers() | no_return(). woody:http_headers() | no_return().
add_metadata_header(H, V, Headers) when is_binary(H) and is_binary(V) -> add_metadata_header(H, V, Headers) when is_binary(H) and is_binary(V) ->
maps:merge(#{ maps:put(<<?HEADER_META_PREFIX/binary, H/binary>>, V, Headers);
<< ?NORMAL_HEADER_META_PREFIX/binary, H/binary >> => V,
<< ?LEGACY_HEADER_META_PREFIX/binary, H/binary >> => V
}, Headers);
add_metadata_header(H, V, Headers) -> add_metadata_header(H, V, Headers) ->
error(badarg, [H, V, Headers]). error(badarg, [H, V, Headers]).
@ -365,10 +357,7 @@ add_deadline_header(Context, Headers) ->
do_add_deadline_header(undefined, Headers) -> do_add_deadline_header(undefined, Headers) ->
Headers; Headers;
do_add_deadline_header(Deadline, Headers) -> do_add_deadline_header(Deadline, Headers) ->
maps:merge(#{ maps:put(?HEADER_DEADLINE, woody_deadline:to_binary(Deadline), Headers).
?NORMAL_HEADER_DEADLINE => woody_deadline:to_binary(Deadline),
?LEGACY_HEADER_DEADLINE => woody_deadline:to_binary(Deadline)
}, Headers).
add_host_header(#hackney_url{netloc = Netloc}, Headers) -> add_host_header(#hackney_url{netloc = Netloc}, Headers) ->
maps:merge(Headers, #{<<"Host">> => Netloc}). maps:merge(Headers, #{<<"Host">> => Netloc}).

View File

@ -5,38 +5,15 @@
-define(CONTENT_TYPE_THRIFT , <<"application/x-thrift">>). -define(CONTENT_TYPE_THRIFT , <<"application/x-thrift">>).
%% Woody-specific HTTP headers %% Woody-specific HTTP headers
-define(NORMAL_HEADER_PREFIX , <<"woody.">>). -define(HEADER_PREFIX , <<"woody.">>).
-define(NORMAL_HEADER_RPC_ID , << ?NORMAL_HEADER_PREFIX/binary, "span-id">>). -define(HEADER_RPC_ID , <<?HEADER_PREFIX/binary, "span-id">>).
-define(NORMAL_HEADER_RPC_PARENT_ID , << ?NORMAL_HEADER_PREFIX/binary, "parent-id">>). -define(HEADER_RPC_PARENT_ID , <<?HEADER_PREFIX/binary, "parent-id">>).
-define(NORMAL_HEADER_RPC_ROOT_ID , << ?NORMAL_HEADER_PREFIX/binary, "trace-id">>). -define(HEADER_RPC_ROOT_ID , <<?HEADER_PREFIX/binary, "trace-id">>).
-define(NORMAL_HEADER_E_CLASS , << ?NORMAL_HEADER_PREFIX/binary, "error-class">>). -define(HEADER_E_CLASS , <<?HEADER_PREFIX/binary, "error-class">>).
-define(NORMAL_HEADER_E_REASON , << ?NORMAL_HEADER_PREFIX/binary, "error-reason">>). -define(HEADER_E_REASON , <<?HEADER_PREFIX/binary, "error-reason">>).
-define(NORMAL_HEADER_DEADLINE , << ?NORMAL_HEADER_PREFIX/binary, "deadline">>). -define(HEADER_DEADLINE , <<?HEADER_PREFIX/binary, "deadline">>).
-define(NORMAL_HEADER_META_PREFIX , << ?NORMAL_HEADER_PREFIX/binary, "meta.">>). -define(HEADER_META_PREFIX , <<?HEADER_PREFIX/binary, "meta.">>).
-define(NORMAL_HEADER_META_RE , <<"woody\\.meta\\.">>). -define(HEADER_META_RE , <<"woody\\.meta\\.">>).
%% Legacy woody headers
-define(LEGACY_HEADER_PREFIX , <<"x-rbk-">>).
-define(LEGACY_HEADER_RPC_ID , << ?LEGACY_HEADER_PREFIX/binary, "span-id">>).
-define(LEGACY_HEADER_RPC_PARENT_ID , << ?LEGACY_HEADER_PREFIX/binary, "parent-id">>).
-define(LEGACY_HEADER_RPC_ROOT_ID , << ?LEGACY_HEADER_PREFIX/binary, "trace-id">>).
-define(LEGACY_HEADER_E_CLASS , << ?LEGACY_HEADER_PREFIX/binary, "error-class">>).
-define(LEGACY_HEADER_E_REASON , << ?LEGACY_HEADER_PREFIX/binary, "error-reason">>).
-define(LEGACY_HEADER_DEADLINE , << ?LEGACY_HEADER_PREFIX/binary, "deadline">>).
-define(LEGACY_HEADER_META_PREFIX , << ?LEGACY_HEADER_PREFIX/binary, "meta-">>).
-define(LEGACY_HEADER_META_RE , <<"x-rbk-meta-">>).
%% transition period helpers
-define(HEADER(MODE, NORMAL, LEGACY), case MODE of normal -> NORMAL; legacy -> LEGACY end).
-define(HEADER_PREFIX(MODE), ?HEADER(MODE, ?NORMAL_HEADER_PREFIX, ?LEGACY_HEADER_PREFIX)).
-define(HEADER_RPC_ID(MODE), ?HEADER(MODE, ?NORMAL_HEADER_RPC_ID, ?LEGACY_HEADER_RPC_ID)).
-define(HEADER_RPC_PARENT_ID(MODE), ?HEADER(MODE, ?NORMAL_HEADER_RPC_PARENT_ID, ?LEGACY_HEADER_RPC_PARENT_ID)).
-define(HEADER_RPC_ROOT_ID(MODE), ?HEADER(MODE, ?NORMAL_HEADER_RPC_ROOT_ID, ?LEGACY_HEADER_RPC_ROOT_ID)).
-define(HEADER_E_CLASS(MODE), ?HEADER(MODE, ?NORMAL_HEADER_E_CLASS, ?LEGACY_HEADER_E_CLASS)).
-define(HEADER_E_REASON(MODE), ?HEADER(MODE, ?NORMAL_HEADER_E_REASON, ?LEGACY_HEADER_E_REASON)).
-define(HEADER_DEADLINE(MODE), ?HEADER(MODE, ?NORMAL_HEADER_DEADLINE, ?LEGACY_HEADER_DEADLINE)).
-define(HEADER_META_PREFIX(MODE), ?HEADER(MODE, ?NORMAL_HEADER_META_PREFIX, ?LEGACY_HEADER_META_PREFIX)).
-define(HEADER_META_RE(MODE), ?HEADER(MODE, ?NORMAL_HEADER_META_RE, ?LEGACY_HEADER_META_RE)).
%% Events %% Events
-define(EV_CALL_SERVICE , 'call service'). -define(EV_CALL_SERVICE , 'call service').

View File

@ -208,7 +208,7 @@ config() ->
-spec compile_filter_meta() -> -spec compile_filter_meta() ->
re_mp(). re_mp().
compile_filter_meta() -> compile_filter_meta() ->
{ok, Re} = re:compile([?NORMAL_HEADER_META_RE], [unicode, caseless]), {ok, Re} = re:compile(?HEADER_META_RE, [unicode, caseless]),
Re. Re.
-spec trace_req(true, cowboy_req:req(), woody:ev_handlers(), server_opts()) -> -spec trace_req(true, cowboy_req:req(), woody:ev_handlers(), server_opts()) ->
@ -362,33 +362,31 @@ check_accept(BadAccept, Req1, State) ->
-spec check_woody_headers(cowboy_req:req(), state()) -> -spec check_woody_headers(cowboy_req:req(), state()) ->
check_result(). check_result().
check_woody_headers(Req, State = #{woody_state := WoodyState0}) -> check_woody_headers(Req, State = #{woody_state := WoodyState0}) ->
{Mode, Req0} = woody_util:get_req_headers_mode(Req), case get_rpc_id(Req) of
case get_rpc_id(Req0, Mode) of
{ok, RpcId, Req1} -> {ok, RpcId, Req1} ->
WoodyState1 = set_cert(Req1, set_rpc_id(RpcId, WoodyState0)), WoodyState1 = set_cert(Req1, set_rpc_id(RpcId, WoodyState0)),
check_deadline_header( check_deadline_header(
cowboy_req:header(?HEADER_DEADLINE(Mode), Req1), cowboy_req:header(?HEADER_DEADLINE, Req1),
Req1, Req1,
Mode,
update_woody_state(State, WoodyState1, Req1) update_woody_state(State, WoodyState1, Req1)
); );
{error, BadRpcId, Req1} -> {error, BadRpcId, Req1} ->
WoodyState1 = set_rpc_id(BadRpcId, WoodyState0), WoodyState1 = set_rpc_id(BadRpcId, WoodyState0),
reply_bad_header(400, woody_util:to_binary(["bad ", ?HEADER_PREFIX(Mode), " id header"]), reply_bad_header(400, woody_util:to_binary(["bad ", ?HEADER_PREFIX, " id header"]),
Req1, update_woody_state(State, WoodyState1, Req1) Req1, update_woody_state(State, WoodyState1, Req1)
) )
end. end.
-spec get_rpc_id(cowboy_req:req(), woody_util:headers_mode()) -> -spec get_rpc_id(cowboy_req:req()) ->
{ok | error, woody:rpc_id(), cowboy_req:req()}. {ok | error, woody:rpc_id(), cowboy_req:req()}.
get_rpc_id(Req, Mode) -> get_rpc_id(Req) ->
check_ids(maps:fold( check_ids(maps:fold(
fun get_rpc_id/3, fun get_rpc_id/3,
#{req => Req}, #{req => Req},
#{ #{
span_id => ?HEADER_RPC_ID(Mode), span_id => ?HEADER_RPC_ID,
trace_id => ?HEADER_RPC_ROOT_ID(Mode), trace_id => ?HEADER_RPC_ROOT_ID,
parent_id => ?HEADER_RPC_PARENT_ID(Mode) parent_id => ?HEADER_RPC_PARENT_ID
} }
)). )).
@ -405,22 +403,22 @@ check_ids(Map = #{status := error, req := Req}) ->
check_ids(Map = #{req := Req}) -> check_ids(Map = #{req := Req}) ->
{ok, maps:without([req], Map), Req}. {ok, maps:without([req], Map), Req}.
-spec check_deadline_header(Header, Req, woody_util:headers_mode(), state()) -> cowboy_init_result() when -spec check_deadline_header(Header, Req, state()) -> cowboy_init_result() when
Header :: woody:http_header_val() | undefined, Req :: cowboy_req:req(). Header :: woody:http_header_val() | undefined, Req :: cowboy_req:req().
check_deadline_header(undefined, Req, Mode, State) -> check_deadline_header(undefined, Req, State) ->
check_metadata_headers(cowboy_req:headers(Req), Req, Mode, State); check_metadata_headers(cowboy_req:headers(Req), Req, State);
check_deadline_header(DeadlineBin, Req, Mode, State) -> check_deadline_header(DeadlineBin, Req, State) ->
try woody_deadline:from_binary(DeadlineBin) of try woody_deadline:from_binary(DeadlineBin) of
Deadline -> check_deadline(Deadline, Req, Mode, State) Deadline -> check_deadline(Deadline, Req, State)
catch catch
error:{bad_deadline, Error} -> error:{bad_deadline, Error} ->
ErrorDescription = woody_util:to_binary(["bad ", ?HEADER_DEADLINE(Mode), " header: ", Error]), ErrorDescription = woody_util:to_binary(["bad ", ?HEADER_DEADLINE, " header: ", Error]),
reply_bad_header(400, ErrorDescription, Req, State) reply_bad_header(400, ErrorDescription, Req, State)
end. end.
-spec check_deadline(woody:deadline(), cowboy_req:req(), woody_util:headers_mode(), state()) -> -spec check_deadline(woody:deadline(), cowboy_req:req(), state()) ->
check_result(). check_result().
check_deadline(Deadline, Req, Mode, State = #{url := Url, woody_state := WoodyState}) -> check_deadline(Deadline, Req, State = #{url := Url, woody_state := WoodyState}) ->
case woody_deadline:is_reached(Deadline) of case woody_deadline:is_reached(Deadline) of
true -> true ->
_ = woody_event_handler:handle_event(?EV_SERVER_RECEIVE, WoodyState, _ = woody_event_handler:handle_event(?EV_SERVER_RECEIVE, WoodyState,
@ -430,29 +428,28 @@ check_deadline(Deadline, Req, Mode, State = #{url := Url, woody_state := WoodySt
false -> false ->
WoodyState1 = set_deadline(Deadline, WoodyState), WoodyState1 = set_deadline(Deadline, WoodyState),
Headers = cowboy_req:headers(Req), Headers = cowboy_req:headers(Req),
check_metadata_headers(Headers, Req, Mode, update_woody_state(State, WoodyState1, Req)) check_metadata_headers(Headers, Req, update_woody_state(State, WoodyState1, Req))
end. end.
-spec check_metadata_headers(woody:http_headers(), cowboy_req:req(), woody_util:headers_mode(), state()) -> -spec check_metadata_headers(woody:http_headers(), cowboy_req:req(), state()) ->
check_result(). check_result().
check_metadata_headers(Headers, Req, Mode, State = #{woody_state := WoodyState, server_opts := ServerOpts}) -> check_metadata_headers(Headers, Req, State = #{woody_state := WoodyState, server_opts := ServerOpts}) ->
WoodyState1 = set_metadata(find_metadata(Headers, Mode, ServerOpts), WoodyState), WoodyState1 = set_metadata(find_metadata(Headers, ServerOpts), WoodyState),
{ok, Req, update_woody_state(State, WoodyState1, Req)}. {ok, Req, update_woody_state(State, WoodyState1, Req)}.
-spec find_metadata(woody:http_headers(), woody_util:headers_mode(), server_opts()) -> -spec find_metadata(woody:http_headers(), server_opts()) ->
woody_context:meta(). woody_context:meta().
find_metadata(Headers, Mode, #{regexp_meta := _Re}) -> find_metadata(Headers, #{regexp_meta := Re}) ->
%% TODO: Use compiled Re after headers transition ends RpcId = ?HEADER_RPC_ID,
RpcId = ?HEADER_RPC_ID(Mode), RootId = ?HEADER_RPC_ROOT_ID,
RootId = ?HEADER_RPC_ROOT_ID(Mode), ParentId = ?HEADER_RPC_PARENT_ID,
ParentId = ?HEADER_RPC_PARENT_ID(Mode),
maps:fold( maps:fold(
fun(H, V, Acc) when fun(H, V, Acc) when
H =/= RpcId andalso H =/= RpcId andalso
H =/= RootId andalso H =/= RootId andalso
H =/= ParentId H =/= ParentId
-> ->
case re:replace(H, ?HEADER_META_RE(Mode), "", [{return, binary}, anchored]) of case re:replace(H, Re, "", [{return, binary}, anchored]) of
H -> Acc; H -> Acc;
MetaHeader -> Acc#{MetaHeader => V} MetaHeader -> Acc#{MetaHeader => V}
end; end;
@ -556,10 +553,8 @@ handle_error({system, {external, result_unknown, Details}}, Req, WoodyState) ->
cowboy_req:req(). cowboy_req:req().
set_error_headers(Class, Reason, Req) -> set_error_headers(Class, Reason, Req) ->
Headers = #{ Headers = #{
?NORMAL_HEADER_E_CLASS => Class, ?HEADER_E_CLASS => Class,
?NORMAL_HEADER_E_REASON => Reason, ?HEADER_E_REASON => Reason
?LEGACY_HEADER_E_CLASS => Class,
?LEGACY_HEADER_E_REASON =>Reason
}, },
cowboy_req:set_resp_headers(Headers, Req). cowboy_req:set_resp_headers(Headers, Req).

View File

@ -2,21 +2,14 @@
%%% @end %%% @end
-module(woody_util). -module(woody_util).
-include("woody_defs.hrl").
-export([get_protocol_handler/2]). -export([get_protocol_handler/2]).
-export([get_mod_opts/1]). -export([get_mod_opts/1]).
-export([to_binary/1]). -export([to_binary/1]).
-export([get_rpc_reply_type/1]). -export([get_rpc_reply_type/1]).
-export([get_req_headers_mode/1]).
-export([get_error_headers_mode/1]).
-export_type([headers_mode/0]).
-define(DEFAULT_HANDLER_OPTS, undefined). -define(DEFAULT_HANDLER_OPTS, undefined).
-type headers_mode() :: normal | legacy.
%% %%
%% Internal API %% Internal API
%% %%
@ -55,60 +48,3 @@ to_binary([Part | T], Reason) ->
woody:rpc_type(). woody:rpc_type().
get_rpc_reply_type(oneway_void) -> cast; get_rpc_reply_type(oneway_void) -> cast;
get_rpc_reply_type(_) -> call. get_rpc_reply_type(_) -> call.
-spec get_req_headers_mode(cowboy_req:req()) ->
{headers_mode(), cowboy_req:req()}.
get_req_headers_mode(Req) ->
get_req_headers_mode(application:get_env(woody, server_headers_mode, auto), Req).
-spec get_error_headers_mode(woody:http_headers()) ->
headers_mode().
get_error_headers_mode(Headers) ->
get_error_headers_mode(application:get_env(woody, client_headers_mode, auto), Headers).
%%
%% Internals
%%
apply_mode_rules([], _Rules, Default) ->
Default;
apply_mode_rules([Name | HeadersTail], Rules, Default) ->
case maps:get(Name, Rules, undefined) of
undefined ->
apply_mode_rules(HeadersTail, Rules, Default);
Mode ->
Mode
end.
-spec get_req_headers_mode(auto | headers_mode(), cowboy_req:req()) ->
{headers_mode(), cowboy_req:req()}.
get_req_headers_mode(auto, Req) ->
Rules = #{
?NORMAL_HEADER_RPC_ID => normal,
?NORMAL_HEADER_RPC_PARENT_ID => normal,
?NORMAL_HEADER_RPC_ROOT_ID => normal
},
Headers = cowboy_req:headers(Req),
{apply_mode_rules(maps:keys(Headers), Rules, legacy), Req};
get_req_headers_mode(legacy = Mode, Req) ->
{Mode, Req};
get_req_headers_mode(normal = Mode, Req) ->
{Mode, Req};
get_req_headers_mode(Mode, _Req) ->
erlang:error(badarg, [Mode]).
-spec get_error_headers_mode(auto | headers_mode(), woody:http_headers()) ->
headers_mode().
get_error_headers_mode(auto, Headers) ->
Rules = #{
?NORMAL_HEADER_E_CLASS => normal,
?NORMAL_HEADER_E_REASON => normal
},
apply_mode_rules(maps:keys(Headers), Rules, legacy);
get_error_headers_mode(legacy = Mode, _Headers) ->
Mode;
get_error_headers_mode(normal = Mode, _Headers) ->
Mode;
get_error_headers_mode(Mode, _Headers) ->
erlang:error(badarg, [Mode]).

View File

@ -240,11 +240,7 @@
%% %%
all() -> all() ->
[ [
{group, legacy_client_auto_server}, {group, client_server},
{group, auto_client_legacy_server},
{group, auto_both},
{group, normal_both},
{group, legacy_both},
{group, woody_resolver} {group, woody_resolver}
]. ].
@ -295,11 +291,7 @@ groups() ->
calls_with_cache calls_with_cache
], ],
[ [
{legacy_client_auto_server, [], SpecTests}, {client_server, [], SpecTests},
{auto_client_legacy_server, [], SpecTests},
{auto_both, [], SpecTests},
{normal_both, [], SpecTests},
{legacy_both, [], SpecTests},
{woody_resolver, [], [ {woody_resolver, [], [
woody_resolver_inet, woody_resolver_inet,
woody_resolver_inet6, woody_resolver_inet6,
@ -331,17 +323,7 @@ init_per_suite(C) ->
end_per_suite(C) -> end_per_suite(C) ->
application:unset_env(hackney, mod_metrics), % unset so it won't report metrics next suite application:unset_env(hackney, mod_metrics), % unset so it won't report metrics next suite
[application_stop(App) || App <- proplists:get_value(apps, C)]. [application:stop(App) || App <- proplists:get_value(apps, C)].
application_stop(App=sasl) ->
%% hack for preventing sasl deadlock
%% http://erlang.org/pipermail/erlang-questions/2014-May/079012.html
error_logger:delete_report_handler(cth_log_redirect),
_ = application:stop(App),
error_logger:add_report_handler(cth_log_redirect),
ok;
application_stop(App) ->
application:stop(App).
init_per_testcase(TC, C) when init_per_testcase(TC, C) when
TC =:= try_bad_handler_spec_test ; TC =:= try_bad_handler_spec_test ;
@ -387,46 +369,14 @@ init_per_testcase(_, C) ->
{ok, _} = start_woody_server(woody_ct, Sup, ['Weapons', 'Powerups']), {ok, _} = start_woody_server(woody_ct, Sup, ['Weapons', 'Powerups']),
[{sup, Sup} | C]. [{sup, Sup} | C].
init_per_group(legacy_client_auto_server, Config) ->
config_headers_mode(legacy, auto, Config);
init_per_group(auto_client_legacy_server, Config) ->
config_headers_mode(auto, legacy, Config);
init_per_group(auto_both, Config) ->
config_headers_mode(auto, auto, Config);
init_per_group(normal_both, Config) ->
config_headers_mode(normal, normal, Config);
init_per_group(legacy_both, Config) ->
config_headers_mode(legacy, legacy, Config);
init_per_group(woody_resolver, Config) -> init_per_group(woody_resolver, Config) ->
Config0 = config_headers_mode(normal, normal, Config), [{env_inet6, inet_db:res_option(inet6)} | Config];
[{env_inet6, inet_db:res_option(inet6)} | Config0];
init_per_group(_Name, Config) -> init_per_group(_Name, Config) ->
Config. Config.
end_per_group(Name, _Config) when
Name =:= legacy_client_auto_server orelse
Name =:= auto_client_legacy_server orelse
Name =:= auto_both orelse
Name =:= normal_both orelse
Name =:= legacy_both orelse
Name =:= woody_resolver
->
ok = application:set_env(woody, client_headers_mode, auto),
ok = application:set_env(woody, server_headers_mode, auto),
ok;
end_per_group(_Name, _Config) -> end_per_group(_Name, _Config) ->
ok. ok.
config_headers_mode(Client, Server, Config) ->
ok = application:set_env(woody, client_headers_mode, Client),
ok = application:set_env(woody, server_headers_mode, Server),
[{server_headers_mode, not_auto(Server)}, {client_headers_mode, not_auto(Client)} | Config].
not_auto(auto) ->
normal;
not_auto(Mode) ->
Mode.
start_tc_sup() -> start_tc_sup() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
@ -883,16 +833,15 @@ call_deadline_timeout_test(_) ->
woody_client:call(Request, Opts, Context) woody_client:call(Request, Opts, Context)
). ).
server_http_req_validation_test(Config) -> server_http_req_validation_test(_Config) ->
HeadersMode = proplists:get_value(client_headers_mode, Config),
Id = <<"server_http_req_validation">>, Id = <<"server_http_req_validation">>,
{Url, _Service} = get_service_endpoint('Weapons'), {Url, _Service} = get_service_endpoint('Weapons'),
Headers = [ Headers = [
{?HEADER_RPC_ROOT_ID(HeadersMode) , genlib:to_binary(Id)}, {?HEADER_RPC_ROOT_ID , genlib:to_binary(Id)},
{?HEADER_RPC_ID(HeadersMode) , genlib:to_binary(Id)}, {?HEADER_RPC_ID , genlib:to_binary(Id)},
{?HEADER_RPC_PARENT_ID(HeadersMode) , genlib:to_binary(?ROOT_REQ_PARENT_ID)}, {?HEADER_RPC_PARENT_ID , genlib:to_binary(?ROOT_REQ_PARENT_ID)},
{<<"content-type">> , ?CONTENT_TYPE_THRIFT}, {<<"content-type">> , ?CONTENT_TYPE_THRIFT},
{<<"accept">> , ?CONTENT_TYPE_THRIFT} {<<"accept">> , ?CONTENT_TYPE_THRIFT}
], ],
{ok, _Ref} = timer:kill_after(5000), {ok, _Ref} = timer:kill_after(5000),