diff options
author | Bryan Paxton <39971740+starbelly@users.noreply.github.com> | 2019-03-07 10:54:01 -0600 |
---|---|---|
committer | Tristan Sloughter <t@crashfast.com> | 2019-03-07 09:54:01 -0700 |
commit | 209c02ec57c2cc3207ee0174c3af3675b8dc8f79 (patch) | |
tree | e07b25a27a2c4cc438db75d8d066179b4e57f3f7 /src/r3_hex_api.erl | |
parent | 9e2e54afd74104ecb05c55e033803f41932eb940 (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.erl | 120 |
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)]. |