summaryrefslogtreecommitdiff
path: root/src/r3_hex_api.erl
diff options
context:
space:
mode:
authorBryan Paxton <39971740+starbelly@users.noreply.github.com>2019-03-07 10:54:01 -0600
committerTristan Sloughter <t@crashfast.com>2019-03-07 09:54:01 -0700
commit209c02ec57c2cc3207ee0174c3af3675b8dc8f79 (patch)
treee07b25a27a2c4cc438db75d8d066179b4e57f3f7 /src/r3_hex_api.erl
parent9e2e54afd74104ecb05c55e033803f41932eb940 (diff)
Fix fetching of private packages from orgs on hex repos (#2020)
- vendor in hex_core at v0.5.0 - Change where repo_name should be the org and not the parent - Changed rebar_utils:url_append_path/2 to not explicitly add a '?', this is returned in the Query chunk by http_uri:parse/1 (e.g., "?foo=bar") - update organization_merging test to expect the sub-repo as the repo_name - Add tests for rebar_utils:url_append_path/2 - Stop referencing/setting "organization" in config and use new organization settings (api_repository and repo_organization) - Do not set (assume) the read key is valid for any/every repo - Set repo_organization and api_repository to org - Update tests to check for new config opts
Diffstat (limited to 'src/r3_hex_api.erl')
-rw-r--r--src/r3_hex_api.erl120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/r3_hex_api.erl b/src/r3_hex_api.erl
new file mode 100644
index 0000000..09d9bcf
--- /dev/null
+++ b/src/r3_hex_api.erl
@@ -0,0 +1,120 @@
+%% Vendored from hex_core v0.5.0, do not edit manually
+
+%% @hidden
+
+-module(r3_hex_api).
+
+-export([
+ delete/2,
+ get/2,
+ post/3,
+ put/3,
+ encode_query_string/1,
+ build_repository_path/2,
+ build_organization_path/2,
+ join_path_segments/1
+]).
+-define(ERL_CONTENT_TYPE, <<"application/vnd.hex+erlang">>).
+
+get(Config, Path) ->
+ request(Config, get, Path, undefined).
+
+post(Config, Path, Body) ->
+ request(Config, post, Path, encode_body(Body)).
+
+put(Config, Path, Body) ->
+ request(Config, put, Path, encode_body(Body)).
+
+delete(Config, Path) ->
+ request(Config, delete, Path, undefined).
+
+%% @private
+encode_query_string(List) ->
+ QueryString =
+ join("&",
+ lists:map(fun
+ ({K, V}) when is_atom(V) ->
+ atom_to_list(K) ++ "=" ++ atom_to_list(V);
+ ({K, V}) when is_binary(V) ->
+ atom_to_list(K) ++ "=" ++ binary_to_list(V);
+ ({K, V}) when is_integer(V) ->
+ atom_to_list(K) ++ "=" ++ integer_to_list(V)
+ end, List)),
+ Encoded = http_uri:encode(QueryString),
+ list_to_binary(Encoded).
+
+%% @private
+build_repository_path(#{api_repository := Repo}, Path) when is_binary(Repo) ->
+ ["repos", Repo | Path];
+build_repository_path(#{api_repository := undefined}, Path) ->
+ Path.
+
+%% @private
+build_organization_path(#{api_organization := Org}, Path) when is_binary(Org) ->
+ ["orgs", Org | Path];
+build_organization_path(#{api_organization := undefined}, Path) ->
+ Path.
+
+%% @private
+join_path_segments(Segments) ->
+ erlang:iolist_to_binary(join(<<"/">>, lists:map(fun encode/1, Segments))).
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+
+request(Config, Method, PathSegments, Body) when is_list(PathSegments) ->
+ Path = join_path_segments(PathSegments),
+ request(Config, Method, Path, Body);
+request(Config, Method, Path, Body) when is_binary(Path) and is_map(Config) ->
+ DefaultHeaders = make_headers(Config),
+ ReqHeaders = maps:merge(maps:get(http_headers, Config, #{}), DefaultHeaders),
+ ReqHeaders2 = put_new(<<"accept">>, ?ERL_CONTENT_TYPE, ReqHeaders),
+
+ case r3_hex_http:request(Config, Method, build_url(Path, Config), ReqHeaders2, Body) of
+ {ok, {Status, RespHeaders, RespBody}} = Response ->
+ ContentType = maps:get(<<"content-type">>, RespHeaders, <<"">>),
+ case binary:match(ContentType, ?ERL_CONTENT_TYPE) of
+ {_, _} ->
+ {ok, {Status, RespHeaders, binary_to_term(RespBody)}};
+
+ nomatch ->
+ Response
+ end;
+
+ Other ->
+ Other
+ end.
+
+encode(Binary) when is_binary(Binary) ->
+ encode(binary_to_list(Binary));
+encode(String) when is_list(String) ->
+ http_uri:encode(String).
+
+build_url(Path, #{api_url := URI}) ->
+ <<URI/binary, "/", Path/binary>>.
+
+encode_body({_ContentType, _Body} = Body) ->
+ Body;
+encode_body(Body) ->
+ {binary_to_list(?ERL_CONTENT_TYPE), term_to_binary(Body)}.
+
+%% TODO: copy-pasted from r3_hex_repo
+make_headers(Config) ->
+ maps:fold(fun set_header/3, #{}, Config).
+
+set_header(api_key, Token, Headers) when is_binary(Token) -> maps:put(<<"authorization">>, Token, Headers);
+set_header(_, _, Headers) -> Headers.
+
+put_new(Key, Value, Map) ->
+ case maps:find(Key, Map) of
+ {ok, _} -> Map;
+ error -> maps:put(Key, Value, Map)
+ end.
+
+%% https://github.com/erlang/otp/blob/OTP-20.3/lib/stdlib/src/lists.erl#L1449:L1453
+join(_Sep, []) -> [];
+join(Sep, [H|T]) -> [H|join_prepend(Sep, T)].
+
+join_prepend(_Sep, []) -> [];
+join_prepend(Sep, [H|T]) -> [Sep,H|join_prepend(Sep,T)].