Skip to content
Permalink
Browse files

Set up mint to allow fetching of a README for any GitHub repo

Run the following command to test this out:

$ mix run -e 'IO.puts AwesomeToolbox.Github.readme("minhajuddin/awesome_toolbox")'
  • Loading branch information...
Khaja Minhajuddin
Khaja Minhajuddin committed Mar 18, 2019
1 parent 164a274 commit 299a0790aa2123d4a2c298621c5cdceb0a6c2dc7
Showing with 69 additions and 1 deletion.
  1. +66 −0 lib/awesome_toolbox/github.ex
  2. +2 −1 mix.exs
  3. +1 −0 mix.lock
@@ -33,4 +33,70 @@ defmodule AwesomeToolbox.Github do
Mint.HTTP.close(conn)
end
end

def readme(repo_full_name) do
{:ok, conn} = Mint.HTTP.connect(:https, "api.github.com", 443)

{:ok, conn, request_ref} =
Mint.HTTP.request(conn, "GET", "/repos/#{repo_full_name}/readme", [
{"content-type", "application/json"}
])

# we now rely on the recv_response function to receive as many messages as
# needed and process them till we have a full response body
{:ok, conn, body} = recv_response(conn, request_ref)

json = Jason.decode!(body)

readme = Base.decode64!(json["content"], ignore: :whitespace)

Mint.HTTP.close(conn)
readme
end

# receive and parse the response till we get a :done mint response
defp recv_response(conn, request_ref, body \\ []) do
{conn, body, status} =
receive do
message ->
# send received message to `Mint` to be parsed
{:ok, conn, mint_responses} = Mint.HTTP.stream(conn, message)

# reduce all the mint responses returning a partial body and status
{body, status} =
Enum.reduce(mint_responses, {body, :incomplete}, fn mint_response, {body, _status} ->
case mint_response do
# the :status mint-response doesn't add anything to the body and receiving this
# doesn't signify the end of the response, let's ignore this for now.
{:status, ^request_ref, _status_code} ->
{body, :incomplete}

# the :headers mint-response doesn't add anything to the body and receiving this
# doesn't signify the end of the response, let's ignore this for now.
{:headers, ^request_ref, _headers} ->
{body, :incomplete}

# the :data mint-response returns a partial body, let us append this
# to the end of our accumulator, this still doesn't signify the end
# of our response, so let's continue
{:data, ^request_ref, data} ->
{body ++ [data], :incomplete}

# the :done mint-response signifies the end of the response
{:done, ^request_ref} ->
{body, :complete}
end
end)

{conn, body, status}
end

# if the status is complete we can return the body which was accumulated till now
if status == :complete do
{:ok, conn, body}
# else we make a tail recursive call to get more messages
else
recv_response(conn, request_ref, body)
end
end
end
@@ -23,7 +23,8 @@ defmodule AwesomeToolbox.MixProject do
defp deps do
[
{:mint, ">= 0.0.0"},
{:castore, ">= 0.0.0"}
{:castore, ">= 0.0.0"},
{:jason, ">= 0.0.0"}
]
end
end
@@ -1,4 +1,5 @@
%{
"castore": {:hex, :castore, "0.1.1", "a8905530209152ddb74989fa2a5bd4fa3a2d3ff5d15ad12578caa7460d807c8b", [:mix], [], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"mint": {:hex, :mint, "0.1.0", "f5a82a909bb95a03222e0cfa5384c287f04c271fd2363e81323020cd33c70712", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm"},
}

0 comments on commit 299a079

Please sign in to comment.
You can’t perform that action at this time.