Skip to content

Commit

Permalink
make egithub_webhook:request() type opaque
Browse files Browse the repository at this point in the history
and move creation and extraction into its own module
  • Loading branch information
Matthias Wahl committed Oct 28, 2016
1 parent 8c7da6c commit 5e04292
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 11 deletions.
19 changes: 8 additions & 11 deletions src/egithub_webhook.erl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@

-export([event/3, event/6]).

-export_type([request/0]).

-type request() :: #{headers => map(), body => binary()}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Callbacks
Expand Down Expand Up @@ -40,14 +37,15 @@
%% @doc Should be called from the endpoint that handles the GitHub's request
%% for the webhook.
%% @end
-spec event(atom(), egithub:credentials(), request()) -> ok | {error, term()}.
event(Module, Cred, #{headers := Headers, body := Body}) ->
case maps:get(<<"x-github-event">>, Headers, undefined) of
-spec event(atom(), egithub:credentials(), egithub_webhook_req:request()) ->
ok | {error, term()}.
event(Module, Cred, Request) ->
case egithub_webhook_req:header(<<"x-github-event">>, Request) of
undefined ->
{error, missing_header};
<<"ping">> -> ok;
<<"pull_request">> ->
EventData = egithub_json:decode(Body),
{_Request2, EventData} = egithub_webhook_req:payload(Request),
case do_handle_pull_request(Module, Cred, EventData) of
clean -> ok;
{clean, _TargetUrl} -> ok;
Expand All @@ -68,15 +66,14 @@ event(Module, Cred, #{headers := Headers, body := Body}) ->
%% @end
-spec event(
atom(), egithub:credentials(), string(), string(), egithub:credentials(),
request()) -> ok | {error, term()}.
egithub_webhook_req:request()) -> ok | {error, term()}.
event(Module, StatusCred, ToolName, Context, CommentsCred, Request) ->
#{headers := Headers, body := Body} = Request,
case maps:get(<<"x-github-event">>, Headers, undefined) of
case egithub_webhook_req:header(<<"x-github-event">>, Request) of
undefined ->
{error, missing_header};
<<"ping">> -> ok;
<<"pull_request">> ->
EventData = egithub_json:decode(Body),
{_Request2, EventData} = egithub_webhook_req:payload(Request),
set_status(pending, StatusCred, ToolName, Context, EventData),
try
Result = do_handle_pull_request(Module, CommentsCred, EventData),
Expand Down
40 changes: 40 additions & 0 deletions src/egithub_webhook_req.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
%%%-------------------------------------------------------------------
%%% @author mwahl
%%% @copyright (C) 2016, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 28. Oct 2016 11:11 AM
%%%-------------------------------------------------------------------
-module(egithub_webhook_req).
-author("mwahl").

-opaque request() :: #{headers => map(), body => map()|binary()}.
-export_type([request/0]).

%% API
-export([new/2, headers/1, header/2, header/3, payload/1]).

-spec new(map(), binary()|map()) -> request().
new(Headers, Body) -> #{headers => Headers, body => Body}.

-spec headers(request()) -> map().
headers(#{headers := Headers}) -> Headers.

-spec header(binary(), request()) -> binary()|undefined.
header(Header, Request) -> header(Header, Request, undefined).

-spec header(binary(), request(), binary()|undefined) -> binary()|undefined.
header(Header, #{headers := Headers}, Default) ->
maps:get(Header, Headers, Default).

-spec payload(request()) -> {request(), map()}.
payload(Request=#{body := Body}) when is_binary(Body)->
with_decoded_body(Request);
payload(Request=#{body := DecodedBody}) when is_map(DecodedBody) ->
{Request, DecodedBody}.

-spec with_decoded_body(request()) -> {request(), map()}.
with_decoded_body(Request=#{body := Body}) ->
DecodedBody = egithub_json:decode(Body),
{Request#{body => DecodedBody}, DecodedBody}.
68 changes: 68 additions & 0 deletions test/egithub_webhook_req_tests.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
%%%-------------------------------------------------------------------
%%% @author mwahl
%%% @copyright (C) 2016, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 28. Oct 2016 11:40 AM
%%%-------------------------------------------------------------------
-module(egithub_webhook_req_tests).
-author("mwahl").

-include_lib("eunit/include/eunit.hrl").

setup_test_data() ->
EncodedBody = <<"{\"foo\":\"bar\"}">>,
DecodedBody = egithub_json:decode(EncodedBody),
TestHeaders = #{<<"Accept">> => <<"*">>,
<<"Content-Type">> => <<"application/json">>},
EncodedReq = egithub_webhook_req:new(TestHeaders, EncodedBody),
DecodedReq = egithub_webhook_req:new(TestHeaders, DecodedBody),
#{
encoded_body => EncodedBody,
decoded_body => DecodedBody,
headers => TestHeaders,
encoded_request => EncodedReq,
decoded_request => DecodedReq
}.

egithub_webhook_req_headers_test_() ->
#{headers := TestHeaders, encoded_request := Req} = setup_test_data(),
[
?_assertEqual(
TestHeaders,
egithub_webhook_req:headers(Req)
),
?_assertEqual(
undefined,
egithub_webhook_req:header(<<"Undefined">>, Req)
),
?_assertEqual(
<<"*">>,
egithub_webhook_req:header(<<"Accept">>, Req)
)
].

egithub_webhook_req_encoded_body_test() ->
#{
encoded_request := Req,
decoded_body := DecodedBody
} = setup_test_data(),
?assertEqual(
{DecodedBody, DecodedBody},
begin
{Req2, Payload1} = egithub_webhook_req:payload(Req),
{_Req3, Payload2} = egithub_webhook_req:payload(Req2),
{Payload1, Payload2}
end
).

egithub_webhook_req_decoded_body_test() ->
#{
decoded_request := Req,
decoded_body := DecodedBody
} = setup_test_data(),
?assertEqual(
{Req, DecodedBody},
egithub_webhook_req:payload(Req)
).

0 comments on commit 5e04292

Please sign in to comment.