-module(forward_handler).
-behavior(cowboy_rest).
-export([init/2]).
-export([allowed_methods/2]).
-export([content_types_accepted/2]).
-export([content_types_provided/2]).
-export([resource_exists/2]).
-export([from_json/2]).
-export([to_json/2]).
init(Req, State) ->
{cowboy_rest, Req, State}.
allowed_methods(Req, State) ->
{[<<"POST">>, <<"OPTIONS">>], Req, State}.
content_types_accepted(Req, State) ->
{[
{<<"application/json">>, from_json}
],
Req, State}.
content_types_provided(Req, State) ->
{[
{<<"application/json">>, to_json}
], Req, State}.
resource_exists(Req, State) ->
{false, Req, State}.
from_json(Req, State) ->
{ok, Body, Req1} = cowboy_req:read_body(Req),
{ok, Data} = thoas:decode(Body),
Result = forward(Data),
ResultJSON = thoas:encode(Result),
Req2 = cowboy_req:set_resp_body(ResultJSON, Req1),
{true, Req2, State}.
to_json(Req, State) ->
{true, Req, State}.
forward(Data) ->
forward(Data, []).
forward([], Result) ->
Result;
forward([#{<<"uri">> := URI,
<<"payload">> := Payload}|Tail], Result) ->
JSONBody = thoas:encode(Payload),
case httpc:request(post, {URI, [], "application/json", JSONBody}, [], []) of
{ok, {{_, 200, _}, _Headers, Response}} ->
{ok, ResponseMap} = thoas:decode(list_to_binary(Response)),
forward(Tail, [#{uri => URI, payload => Payload, result => ResponseMap}|Result]);
{ok, {_StatusLine, _Headers, _Response}} ->
forward(Tail, [#{uri => URI, payload => Payload, result => failed}|Result])
end.