From 0ccb48ce91b213f882304664c6631ee80864c0b5 Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Thu, 30 May 2019 11:06:46 +0300 Subject: [PATCH] Move http request into its own module --- apps/epp_proxy/include/epp_proxy.hrl | 12 +++- apps/epp_proxy/src/epp_http_client.erl | 68 ++++++++++++++++++- .../src/epp_http_client_behaviour.erl | 2 + apps/epp_proxy/src/epp_tls_worker.erl | 38 ++++++----- 4 files changed, 100 insertions(+), 20 deletions(-) diff --git a/apps/epp_proxy/include/epp_proxy.hrl b/apps/epp_proxy/include/epp_proxy.hrl index 08a8a3d..fdc6a2c 100644 --- a/apps/epp_proxy/include/epp_proxy.hrl +++ b/apps/epp_proxy/include/epp_proxy.hrl @@ -12,7 +12,17 @@ url, % "https://example.com/some-url" query_params, % {[{<<"msg">>, <<"Some">>}, {<<"code">>, <<"2001">>}]} cookies, % [<<"session=SomeSession; Version=1">>] - headers % [{"User-Agent", <<"EPP proxy">>}, {"Other", <<"Header">>}] + headers % [{"User-Agent", <<"EPP proxy">>}, {"Other", <<"Header">>}] + }). + +%% Unified version of the two records above. Depending on the method, +%% it either encodes parameters into multipart form or query parameters and url. +-record(epp_unified_request, + {method, % get + url, % "https://example.com/some-url" + params, % {[{<<"msg">>, <<"Some">>}, {<<"code">>, <<"2001">>}]} + cookies, % [<<"session=SomeSession; Version=1">>] + headers % [{"User-Agent", <<"EPP proxy">>}, {"Other", <<"Header">>}] }). -type epp_request() :: #epp_request{}. diff --git a/apps/epp_proxy/src/epp_http_client.erl b/apps/epp_proxy/src/epp_http_client.erl index 45f0a22..40ac340 100644 --- a/apps/epp_proxy/src/epp_http_client.erl +++ b/apps/epp_proxy/src/epp_http_client.erl @@ -4,7 +4,7 @@ -behaviour(epp_http_client_behaviour). --export([request/1, error_request/1]). +-export([request/1, error_request/1, request_builder/1]). %% Callback API request(#epp_request{} = Request) -> @@ -21,6 +21,9 @@ error_request(#epp_error_request{} = Request) -> {ok, Body} = hackney:body(ClientRef), {Status, Body}. +request_builder(Map) -> + request_from_map(Map). + %% Private API -spec handle_args(epp_request()) -> list(). handle_args(#epp_request{method=get, url=URL, headers=Headers, body="", @@ -36,3 +39,66 @@ handle_error_args(#epp_error_request{method=get, url=URL, headers=Headers, QueryString = hackney_url:qs(Params), CompleteURL = [URL, <<"?">>, QueryString], [get, CompleteURL, Headers, "", [{cookie, Cookies}, insecure]]. + + +%% Map request and return values. +request_from_map(#{command := "error", session_id := SessionId, + code := Code, message := Message, headers:=Headers, + cl_trid := ClTRID}) -> + URL = epp_router:route_request("error"), + RequestMethod = epp_router:request_method("error"), + Cookie = hackney_cookie:setcookie("session", SessionId, []), + QueryParams = query_params(Code, Message, ClTRID), + Headers=Headers, + Request = #epp_error_request{url=URL, + method=RequestMethod, + query_params=QueryParams, + cookies=[Cookie], + headers=Headers}, + lager:info("Error Request from map: [~p]~n", [Request]), + Request; +request_from_map(#{command := Command, session_id := SessionId, + raw_frame := RawFrame, headers:=Headers, cl_trid := ClTRID}) -> + URL = epp_router:route_request(Command), + RequestMethod = epp_router:request_method(Command), + Cookie = hackney_cookie:setcookie("session", SessionId, []), + Body = request_body(Command, RawFrame, ClTRID), + Headers=Headers, + Request = #epp_request{url=URL, + method=RequestMethod, + body=Body, + cookies=[Cookie], + headers=Headers}, + lager:info("Request from map: [~p]~n", [Request]), + Request; +request_from_map(#{command := Command, session_id := SessionId, + raw_frame := RawFrame, common_name := CommonName, + client_cert := ClientCert, peer_ip := PeerIp, cl_trid := ClTRID}) -> + URL = epp_router:route_request(Command), + RequestMethod = epp_router:request_method(Command), + Cookie = hackney_cookie:setcookie("session", SessionId, []), + Body = request_body(Command, RawFrame, ClTRID), + Headers = [{"SSL_CLIENT_CERT", ClientCert}, + {"SSL_CLIENT_S_DN_CN", CommonName}, + {"User-Agent", <<"EPP proxy">>}, + {"X-Forwarded-for", epp_util:readable_ip(PeerIp)}], + Request = #epp_request{url=URL, + method=RequestMethod, + body=Body, + cookies=[Cookie], + headers=Headers}, + lager:info("Request from map: [~p]~n", [Request]), + Request. + +%% Return form data or an empty list. +request_body("hello", _, _) -> + ""; +request_body(_Command, RawFrame, nomatch) -> + {multipart, [{<<"raw_frame">>, RawFrame}]}; +request_body(_Command, RawFrame, ClTRID) -> + {multipart, [{<<"raw_frame">>, RawFrame}, {<<"clTRID">>, ClTRID}]}. + +query_params(Code, Message, nomatch) -> + [{<<"code">>, Code}, {<<"msg">>, Message}]; +query_params(Code, Message, ClTRID) -> + [{<<"code">>, Code}, {<<"msg">>, Message}, {<<"clTRID">>, ClTRID}]. diff --git a/apps/epp_proxy/src/epp_http_client_behaviour.erl b/apps/epp_proxy/src/epp_http_client_behaviour.erl index fc6d5d3..b8980e1 100644 --- a/apps/epp_proxy/src/epp_http_client_behaviour.erl +++ b/apps/epp_proxy/src/epp_http_client_behaviour.erl @@ -7,3 +7,5 @@ %% Abstract module for http client behaviour. It should call EPP HTTP server %% and return a response back to the caller. -callback request(epp_request()) -> http_response(). +-callback error_request(epp_error_request()) -> http_response(). +-callback request_builder(map()) -> epp_request() | epp_error_request(). diff --git a/apps/epp_proxy/src/epp_tls_worker.erl b/apps/epp_proxy/src/epp_tls_worker.erl index a717338..88272dc 100644 --- a/apps/epp_proxy/src/epp_tls_worker.erl +++ b/apps/epp_proxy/src/epp_tls_worker.erl @@ -22,7 +22,7 @@ headers }). init(Socket) -> - lager:info("Created a worker process"), + lager:info("Created a worker process: [~p]", [self()]), SessionId = epp_util:session_id(self()), {ok, #state{socket=Socket, session_id=SessionId}}. @@ -40,17 +40,20 @@ handle_cast(greeting, State = #state{socket=Socket, session_id=SessionId, headers=Headers}) -> - Request = request_from_map(#{command => "hello", - session_id => SessionId, - raw_frame => "", - headers => Headers, - cl_trid => nomatch}), + Request = epp_http_client:request_builder(#{command => "hello", + session_id => SessionId, + raw_frame => "", + headers => Headers, + cl_trid => nomatch}), {_Status, Body} = epp_http_client:request(Request), frame_to_socket(Body, Socket), gen_server:cast(self(), process_command), {noreply, State#state{socket=Socket, session_id=SessionId}}; + +%% Main loop of processing commands. Ends the connection when command is logout. +%% handle_cast(process_command, State = #state{socket=Socket,session_id=SessionId, headers=Headers}) -> @@ -58,21 +61,21 @@ handle_cast(process_command, case parse_frame(RawFrame) of #valid_frame{command=Command, cl_trid=ClTRID} -> - Request = request_from_map(#{command => Command, - session_id => SessionId, - raw_frame => RawFrame, - headers => Headers, - cl_trid => ClTRID}), + Request = epp_http_client:request_builder(#{command => Command, + session_id => SessionId, + raw_frame => RawFrame, + headers => Headers, + cl_trid => ClTRID}), {_Status, Body} = epp_http_client:request(Request); #invalid_frame{message=Message, code=Code, cl_trid=ClTRID} -> Command = "error", - Request = request_from_map(#{command => Command, - session_id => SessionId, - headers => Headers, - code => Code, - message => Message, - cl_trid => ClTRID}), + Request = epp_http_client:request_builder(#{command => Command, + session_id => SessionId, + headers => Headers, + code => Code, + message => Message, + cl_trid => ClTRID}), {_Status, Body} = epp_http_client:error_request(Request) end, @@ -197,7 +200,6 @@ frame_from_socket(Socket, State) -> Frame = case read_frame(Socket, Length) of {ok, FrameData} -> - io:format("~p~n", [FrameData]), FrameData; {error, _FrameDetails} -> {stop, normal, State}