Skip to content

Commit 4f48e5f

Browse files
authored
Add short URL API (#158)
1 parent 139ff6b commit 4f48e5f

File tree

6 files changed

+85
-13
lines changed

6 files changed

+85
-13
lines changed

.github/workflows/main.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,34 @@ on:
99
jobs:
1010
test:
1111
name: Test
12-
runs-on: ubuntu-20.04
12+
runs-on: ${{ matrix.pair.os }}
1313
strategy:
1414
fail-fast: false
1515
matrix:
1616
pair:
1717
- erlang: master
18-
rebar3: 3.23.0
18+
rebar3: 3.25.0
19+
os: ubuntu-24.04
20+
21+
- erlang: 28
22+
rebar3: 3.25.0
23+
os: ubuntu-24.04
1924

2025
- erlang: 27
2126
rebar3: 3.23.0
27+
os: ubuntu-22.04
2228

2329
- erlang: 26
2430
rebar3: 3.21.0
31+
os: ubuntu-22.04
2532

2633
- erlang: 25
2734
rebar3: 3.21.0
35+
os: ubuntu-22.04
2836

2937
- erlang: 24
3038
rebar3: 3.21.0
31-
32-
- erlang: 23
33-
rebar3: 3.20.0
34-
35-
- erlang: 22
36-
rebar3: 3.18.0
37-
38-
- erlang: 21
39-
rebar3: 3.15.2
39+
os: ubuntu-22.04
4040
steps:
4141
- uses: actions/checkout@v4
4242

src/hex_api_short_url.erl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
%% @doc
2+
%% Hex HTTP API - Short URLs.
3+
-module(hex_api_short_url).
4+
-export([create/2]).
5+
6+
%% @doc
7+
%% Creates a short URL.
8+
%%
9+
%% Examples:
10+
%%
11+
%% ```
12+
%% > hex_api_short_url:create(hex_core:default_config(), <<"https://hex.pm/packages/example">>).
13+
%% {ok, {201, ..., #{<<"url">> => <<"https://hex.pm/l/XXXXX">>}}}
14+
%% '''
15+
%% @end
16+
-spec create(hex_core:config(), binary()) -> hex_api:response().
17+
create(Config, URL) when is_map(Config) and is_binary(URL) ->
18+
Body = #{<<"url">> => URL},
19+
hex_api:post(Config, ["short_url"], Body).

src/hex_repo.erl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
get_package/2,
88
get_tarball/3,
99
get_docs/3,
10-
get_public_key/1
10+
get_public_key/1,
11+
get_hex_installs/1
1112
]).
1213

1314
%%====================================================================
@@ -143,6 +144,27 @@ get_public_key(Config) ->
143144
Other
144145
end.
145146

147+
%% @doc
148+
%% Gets Hex installation versions CSV from repository.
149+
%%
150+
%% Examples:
151+
%%
152+
%% ```
153+
%% > hex_repo:get_hex_installs(hex_core:default_config()).
154+
%% {ok, {200, ..., <<"1.0.0,abc123,1.13.0\n1.1.0,def456,1.14.0\n...">>}}
155+
%% '''
156+
%% @end
157+
get_hex_installs(Config) ->
158+
ReqHeaders = make_headers(Config),
159+
URI = build_url(Config, <<"installs/hex-1.x.csv">>),
160+
161+
case get(Config, URI, ReqHeaders) of
162+
{ok, {200, RespHeaders, CSV}} ->
163+
{ok, {200, RespHeaders, CSV}};
164+
Other ->
165+
Other
166+
end.
167+
146168
%%====================================================================
147169
%% Internal functions
148170
%%====================================================================

test/hex_api_SUITE.erl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ suite() ->
1919
[{require, {ssl_certs, [test_pub, test_priv]}}].
2020

2121
all() ->
22-
[package_test, release_test, replace_test, user_test, owner_test, keys_test, auth_test].
22+
[package_test, release_test, replace_test, user_test, owner_test, keys_test, auth_test, short_url_test].
2323

2424
package_test(_Config) ->
2525
{ok, {200, _, Package}} = hex_api_package:get(?CONFIG, <<"ecto">>),
@@ -92,3 +92,11 @@ keys_test(_Config) ->
9292

9393
{ok, {200, _, #{<<"name">> := Name2}}} = hex_api_key:delete(?CONFIG, Name2),
9494
ok.
95+
96+
short_url_test(_Config) ->
97+
LongURL = <<"https://hex.pm/packages/ecto">>,
98+
{ok, {201, _, Response}} = hex_api_short_url:create(?CONFIG, LongURL),
99+
#{<<"url">> := ShortURL} = Response,
100+
?assert(is_binary(ShortURL)),
101+
?assert(binary:match(ShortURL, <<"https://hex.pm/l/">>) =/= nomatch),
102+
ok.

test/hex_repo_SUITE.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ all() ->
2525
get_package_test,
2626
get_tarball_test,
2727
get_docs_test,
28+
get_hex_installs_test,
2829
get_public_key_test,
2930
repo_org_not_set
3031
].
@@ -79,6 +80,12 @@ get_docs_test(_Config) ->
7980
{ok, {403, _, _}} = hex_repo:get_docs(?CONFIG, <<"ecto">>, <<"9.9.9">>),
8081
ok.
8182

83+
get_hex_installs_test(_Config) ->
84+
{ok, {200, _, CSV}} = hex_repo:get_hex_installs(?CONFIG),
85+
?assert(is_binary(CSV)),
86+
?assert(binary:match(CSV, <<"1.0.0,abc123,1.13.0\n">>) =/= nomatch),
87+
ok.
88+
8289
get_public_key_test(_Config) ->
8390
{ok, {200, #{<<"etag">> := ETag}, PublicKey}} = hex_repo:get_public_key(?CONFIG),
8491
[{'SubjectPublicKeyInfo', _, not_encrypted}] = public_key:pem_decode(PublicKey),

test/support/hex_http_test.erl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ fixture(get, <<?TEST_REPO_URL, "/docs/ecto-1.0.0.tar.gz">>, _, _) ->
9999
{ok, Docs} = hex_tarball:create_docs([]),
100100
{ok, {200, Headers, Docs}};
101101

102+
fixture(get, <<?TEST_REPO_URL, "/installs/hex-1.x.csv">>, _, _) ->
103+
Headers = #{
104+
<<"etag">> => <<"\"dummy\"">>
105+
},
106+
CSV = <<"1.0.0,abc123,1.13.0\n1.1.0,def456,1.14.0\n">>,
107+
{ok, {200, Headers, CSV}};
108+
102109
fixture(get, <<?TEST_REPO_URL, "/public_key">>, _, _) ->
103110
Headers = #{
104111
<<"etag">> => <<"\"dummy\"">>
@@ -233,6 +240,15 @@ fixture(delete, <<?TEST_API_URL, "/keys/", Name/binary>>, #{<<"authorization">>
233240
},
234241
{ok, {200, api_headers(), term_to_binary(Payload)}};
235242

243+
fixture(post, <<?TEST_API_URL, "/short_url">>, _, {_, Body}) ->
244+
DecodedBody = binary_to_term(Body),
245+
#{<<"url">> := URL} = DecodedBody,
246+
ShortURL = <<"https://hex.pm/l/", (integer_to_binary(erlang:phash2(URL)))/binary>>,
247+
Payload = #{
248+
<<"url">> => ShortURL
249+
},
250+
{ok, {201, api_headers(), term_to_binary(Payload)}};
251+
236252
%% Other
237253

238254
fixture(Method, URI, _, _) ->

0 commit comments

Comments
 (0)