Packages
rebar3_hex
2.1.0
7.1.0
7.0.11
7.0.10
7.0.9
7.0.8
7.0.7
7.0.6
7.0.5
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.11.9
6.11.8
6.11.7
6.11.6
6.11.5
6.11.4
6.11.3
6.11.2
6.11.1
6.11.0
6.10.3
6.10.2
6.10.1
6.10.0
6.9.6
6.9.5
6.9.4
6.9.3
6.9.2
6.9.1
6.9.0
6.8.0
6.7.0
6.6.0
6.5.0
6.4.0
6.3.0
6.2.0
6.1.0
6.0.0
4.1.0
4.0.0
3.1.0
3.0.0
2.5.1
2.5.0
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.20.0
1.19.0
1.18.0
1.17.0
1.16.0
1.15.0
1.14.0
1.13.0
1.12.0
1.11.0
1.10.0
1.9.1
1.9.0
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.3
1.6.1
1.6.0
1.5.0
1.4.0
1.3.0
1.2.0
1.1.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Hex.pm plugin for rebar3
Current section
Files
Jump to
Current section
Files
src/rebar3_hex_http.erl
-module(rebar3_hex_http).
-export([get/2
,delete/2
,put/3
,post_map/3
,post/4
,encode/1
,pretty_print_status/1
,maybe_setup_proxy/0
,user_agent/0]).
-include("rebar3_hex.hrl").
-include_lib("public_key/include/OTP-PUB-KEY.hrl").
-define(ENDPOINT, "/api").
get(Path, Auth) ->
case httpc:request(get, request(Path, Auth)
,[{ssl, rebar_api:ssl_opts(rebar3_hex_config:api_url())}, {relaxed, true}]
,[{body_format, binary}]
,hex) of
{ok, {{_, 200, _}, _, RespBody}} ->
{ok, binary_to_term(RespBody)};
{ok, {{_, Status, _}, _, _}} ->
{error, Status}
end.
delete(Path, Auth) ->
case httpc:request(delete, request(Path, Auth)
,[{ssl, rebar_api:ssl_opts(rebar3_hex_config:api_url())}]
,[{body_format, binary}]
,hex) of
{ok, {{_, 204, _}, _, _}} ->
ok;
{ok, {{_, Status, _}, _, _}} ->
{error, Status}
end.
put(Path, Auth, Body) ->
case httpc:request(put, map_request(Path, Auth, Body)
,[{ssl, rebar_api:ssl_opts(rebar3_hex_config:api_url())}]
,[{body_format, binary}]
,hex) of
{ok, {{_, Status, _}, _, _}} when Status >= 200, Status =< 299 ->
ok;
{ok, {{_, Status, _}, _, RespBody}} ->
{error, Status, RespBody}
end.
post_map(Path, Auth, Body) ->
case httpc:request(post, map_request(Path, Auth, Body)
,[{ssl, rebar_api:ssl_opts(rebar3_hex_config:api_url())}]
,[{body_format, binary}]
,hex) of
{ok, {{_, 204, _}, _, <<>>}} ->
ok;
{ok, {{_, Status, _}, _, RespBody}} when Status >= 200, Status =< 299 ->
{ok, binary_to_term(RespBody)};
{ok, {{_, Status, _}, _, _}} when Status >= 500->
{error, Status, undefined_server_error};
{ok, {{_, Status, _}, _, RespBody}} ->
{error, Status, binary_to_term(RespBody)}
end.
post(Path, Auth, Tar, Size) ->
Body = fun(S) when S < byte_size(Tar) ->
NewSize = min(S + ?CHUNK, byte_size(Tar)),
Chunk = NewSize - S,
{ok, [binary:part(Tar, S, Chunk)], NewSize};
(_S) ->
eof
end,
case httpc:request(post, file_request(Path, Auth, Body, Size)
,[{ssl, rebar_api:ssl_opts(rebar3_hex_config:api_url())}]
,[{body_format, binary}]
,hex) of
{ok, {{_, Status, _}, _, _RespBody}} when Status >= 200, Status =< 299 ->
ok;
{ok, {{_, Status, _}, _RespHeaders, _RespBodyMap}} when Status >= 500->
{error, Status, undefined_server_error};
{ok, {{_, Status, _}, _RespHeaders, RespBodyMap}} ->
{error, Status, binary_to_term(RespBodyMap)}
end.
pretty_print_status(401) -> "Authentication failed (401)";
pretty_print_status(403) -> "Forbidden (403)";
pretty_print_status(404) -> "Entity not found (404)";
pretty_print_status(422) -> "Validation failed (422)";
pretty_print_status(Code) -> io_lib:format("HTTP status code: ~p", [Code]).
%% Internal Functions
request(Path, Auth) ->
{ec_cnv:to_list(rebar3_hex_config:api_url()) ++ ec_cnv:to_list(filename:join(?ENDPOINT, Path))
,[{"authorization", ec_cnv:to_list(Auth)}, {"user-agent", user_agent()}
, {"Accept", "application/vnd.hex+erlang"}]}.
map_request(Path, Auth, Body) ->
{ec_cnv:to_list(rebar3_hex_config:api_url()) ++ ec_cnv:to_list(filename:join(?ENDPOINT, Path))
,[{"authorization", ec_cnv:to_list(Auth)}, {"user-agent", user_agent()},
{"Accept", "application/vnd.hex+erlang"}]
,"application/vnd.hex+erlang", term_to_binary(Body)}.
file_request(Path, Auth, Body, ContentLength) ->
{ec_cnv:to_list(rebar3_hex_config:api_url()) ++ ec_cnv:to_list(filename:join(?ENDPOINT, Path))
,[{"authorization", ec_cnv:to_list(Auth)}
,{"content-length", ContentLength}, {"user-agent", user_agent()},
{"Accept", "application/vnd.hex+erlang"}] %%Erlang media type
,"application/octet-stream", {Body, 0}}.
maybe_setup_proxy() ->
maybe_setup_proxy(https_proxy, rebar3_hex_config:https_proxy()),
maybe_setup_proxy(proxy, rebar3_hex_config:http_proxy()).
maybe_setup_proxy(_, []) ->
ok;
maybe_setup_proxy(Scheme, Proxy) ->
{ok, {_, _, Host, Port, _, _}} = http_uri:parse(Proxy),
httpc:set_options([{Scheme, {{Host, Port}, []}}], hex).
encode(Term) ->
quote_plus(Term).
-define(PERCENT, 37). % $\%
-define(FULLSTOP, 46). % $\.
-define(IS_HEX(C), ((C >= $0 andalso C =< $9) orelse
(C >= $a andalso C =< $f) orelse
(C >= $A andalso C =< $F))).
-define(QS_SAFE(C), ((C >= $a andalso C =< $z) orelse
(C >= $A andalso C =< $Z) orelse
(C >= $0 andalso C =< $9) orelse
(C =:= ?FULLSTOP orelse C =:= $- orelse C =:= $~ orelse
C =:= $_))).
hexdigit(C) when C < 10 -> $0 + C;
hexdigit(C) when C < 16 -> $A + (C - 10).
%% @spec quote_plus(atom() | integer() | string()) -> string()
%% @doc URL safe encoding of the given term.
quote_plus(Atom) when is_atom(Atom) ->
quote_plus(atom_to_list(Atom));
quote_plus(Int) when is_integer(Int) ->
quote_plus(integer_to_list(Int));
quote_plus(String) ->
quote_plus(String, []).
quote_plus([], Acc) ->
lists:reverse(Acc);
quote_plus([C | Rest], Acc) when ?QS_SAFE(C) ->
quote_plus(Rest, [C | Acc]);
quote_plus([$\s | Rest], Acc) ->
quote_plus(Rest, [$+ | Acc]);
quote_plus([C | Rest], Acc) ->
<<Hi:4, Lo:4>> = <<C>>,
quote_plus(Rest, [hexdigit(Lo), hexdigit(Hi), ?PERCENT | Acc]).
user_agent() ->
application:load(rebar3_hex),
{ok, RebarVsn} = application:get_key(rebar, vsn),
{ok, RebarHexVsn} = application:get_key(rebar3_hex, vsn),
io_lib:format("rebar3_hex/~s (rebar3/~s Erlang/~s)", [RebarHexVsn
,RebarVsn
,rebar_utils:otp_release()]).