您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

120 行
3.7 KiB

  1. %% Vendored from hex_core v0.5.0, do not edit manually
  2. %% @hidden
  3. -module(r3_hex_api).
  4. -export([
  5. delete/2,
  6. get/2,
  7. post/3,
  8. put/3,
  9. encode_query_string/1,
  10. build_repository_path/2,
  11. build_organization_path/2,
  12. join_path_segments/1
  13. ]).
  14. -define(ERL_CONTENT_TYPE, <<"application/vnd.hex+erlang">>).
  15. get(Config, Path) ->
  16. request(Config, get, Path, undefined).
  17. post(Config, Path, Body) ->
  18. request(Config, post, Path, encode_body(Body)).
  19. put(Config, Path, Body) ->
  20. request(Config, put, Path, encode_body(Body)).
  21. delete(Config, Path) ->
  22. request(Config, delete, Path, undefined).
  23. %% @private
  24. encode_query_string(List) ->
  25. QueryString =
  26. join("&",
  27. lists:map(fun
  28. ({K, V}) when is_atom(V) ->
  29. atom_to_list(K) ++ "=" ++ atom_to_list(V);
  30. ({K, V}) when is_binary(V) ->
  31. atom_to_list(K) ++ "=" ++ binary_to_list(V);
  32. ({K, V}) when is_integer(V) ->
  33. atom_to_list(K) ++ "=" ++ integer_to_list(V)
  34. end, List)),
  35. Encoded = http_uri:encode(QueryString),
  36. list_to_binary(Encoded).
  37. %% @private
  38. build_repository_path(#{api_repository := Repo}, Path) when is_binary(Repo) ->
  39. ["repos", Repo | Path];
  40. build_repository_path(#{api_repository := undefined}, Path) ->
  41. Path.
  42. %% @private
  43. build_organization_path(#{api_organization := Org}, Path) when is_binary(Org) ->
  44. ["orgs", Org | Path];
  45. build_organization_path(#{api_organization := undefined}, Path) ->
  46. Path.
  47. %% @private
  48. join_path_segments(Segments) ->
  49. erlang:iolist_to_binary(join(<<"/">>, lists:map(fun encode/1, Segments))).
  50. %%====================================================================
  51. %% Internal functions
  52. %%====================================================================
  53. request(Config, Method, PathSegments, Body) when is_list(PathSegments) ->
  54. Path = join_path_segments(PathSegments),
  55. request(Config, Method, Path, Body);
  56. request(Config, Method, Path, Body) when is_binary(Path) and is_map(Config) ->
  57. DefaultHeaders = make_headers(Config),
  58. ReqHeaders = maps:merge(maps:get(http_headers, Config, #{}), DefaultHeaders),
  59. ReqHeaders2 = put_new(<<"accept">>, ?ERL_CONTENT_TYPE, ReqHeaders),
  60. case r3_hex_http:request(Config, Method, build_url(Path, Config), ReqHeaders2, Body) of
  61. {ok, {Status, RespHeaders, RespBody}} = Response ->
  62. ContentType = maps:get(<<"content-type">>, RespHeaders, <<"">>),
  63. case binary:match(ContentType, ?ERL_CONTENT_TYPE) of
  64. {_, _} ->
  65. {ok, {Status, RespHeaders, binary_to_term(RespBody)}};
  66. nomatch ->
  67. Response
  68. end;
  69. Other ->
  70. Other
  71. end.
  72. encode(Binary) when is_binary(Binary) ->
  73. encode(binary_to_list(Binary));
  74. encode(String) when is_list(String) ->
  75. http_uri:encode(String).
  76. build_url(Path, #{api_url := URI}) ->
  77. <<URI/binary, "/", Path/binary>>.
  78. encode_body({_ContentType, _Body} = Body) ->
  79. Body;
  80. encode_body(Body) ->
  81. {binary_to_list(?ERL_CONTENT_TYPE), term_to_binary(Body)}.
  82. %% TODO: copy-pasted from r3_hex_repo
  83. make_headers(Config) ->
  84. maps:fold(fun set_header/3, #{}, Config).
  85. set_header(api_key, Token, Headers) when is_binary(Token) -> maps:put(<<"authorization">>, Token, Headers);
  86. set_header(_, _, Headers) -> Headers.
  87. put_new(Key, Value, Map) ->
  88. case maps:find(Key, Map) of
  89. {ok, _} -> Map;
  90. error -> maps:put(Key, Value, Map)
  91. end.
  92. %% https://github.com/erlang/otp/blob/OTP-20.3/lib/stdlib/src/lists.erl#L1449:L1453
  93. join(_Sep, []) -> [];
  94. join(Sep, [H|T]) -> [H|join_prepend(Sep, T)].
  95. join_prepend(_Sep, []) -> [];
  96. join_prepend(Sep, [H|T]) -> [Sep,H|join_prepend(Sep,T)].