Browse Source

feat(http): Add wrapper; impl from HTTPotion.

jackyalcine 6 months ago
parent
commit
fc731168e6
Signed by: Jacky Alciné <yo@jacky.wtf> GPG Key ID: 537A4F904B15268D

+ 1
- 0
.tool-versions View File

@@ -0,0 +1 @@
1
+elixir 1.7.4

+ 15
- 0
lib/indieweb/http.ex View File

@@ -0,0 +1,15 @@
1
+defmodule IndieWeb.Http do
2
+  def adapter, do: Application.get_env(:indieweb, :http_adapter, IndieWeb.Http.Adapters.HTTPotion)
3
+
4
+  defmodule Adapter do
5
+    def request(uri, method, opts)
6
+  end
7
+
8
+  def request(uri, method \\ :get, opts \\ []) do
9
+    adapter().request(uri, method, opts)
10
+  end
11
+
12
+  for method <- ~w(get post options head put patch delete)a do
13
+    def unquote(method)(uri, opts), do: IndieWeb.Http.request(uri, unquote(method), opts)
14
+  end
15
+end

+ 4
- 0
lib/indieweb/http/adapter.ex View File

@@ -0,0 +1,4 @@
1
+defmodule IndieWeb.Http.Adapter do
2
+  @callback
3
+  def request(method, uri, opts)
4
+end

+ 22
- 0
lib/indieweb/http/adapters/httpotion.ex View File

@@ -0,0 +1,22 @@
1
+defmodule IndieWeb.Http.Adapters.HTTPotion do
2
+  @impl true
3
+  def request(uri, method, opts) do
4
+    options = [
5
+      timeout: opts[:timeout],
6
+      follow_redirects: true,
7
+      auto_sni: true,
8
+      headers: Keyword.get(opts, :headers, %{}) |> Map.to_list |> Keyword.new,
9
+      direct: nil,
10
+      ibrowse: [],
11
+      body: Keyword.get(opts, :body, nil),
12
+      query: Keyword.get(opts, :query, nil)
13
+    ]
14
+
15
+    case HTTPotion.request(method, uri, options) do
16
+      %HTTPotion.ErrorResponse{} = err_resp ->
17
+        {:error, %IndieWeb.Http.Error{message: err_resp.message, raw: err_resp}}
18
+      %HTTPotion.Response{} = resp ->
19
+        {:ok, %IndieWeb.Http.Response{code: resp.status_code, body: resp.body, headers: resp.headers}}
20
+    end
21
+  end
22
+end

+ 3
- 0
lib/indieweb/http/error.ex View File

@@ -0,0 +1,3 @@
1
+defmodule IndieWeb.Http.Error do
2
+  defstruct ~w(message raw)a
3
+end

+ 3
- 0
lib/indieweb/http/response.ex View File

@@ -0,0 +1,3 @@
1
+defmodule IndieWeb.Http.Response do
2
+  defstruct ~w(body code headers raw)a
3
+end

+ 2
- 2
lib/microformats2/utility.ex View File

@@ -34,7 +34,7 @@ defmodule Microformats2.Utiltiy do
34 34
       {prop, items} ->
35 35
         Stream.flat_map(items, fn
36 36
           item when is_map(item) ->
37
-            parse_item(item, format)
37
+            do_parse_item(item, format)
38 38
 
39 39
           _ ->
40 40
             []
@@ -42,5 +42,5 @@ defmodule Microformats2.Utiltiy do
42 42
     end)
43 43
   end
44 44
 
45
-  def do_extract_from_properties(_, _), do: []
45
+  defp do_extract_from_properties(_, _), do: []
46 46
 end

+ 8
- 1
mix.exs View File

@@ -7,6 +7,7 @@ defmodule IndieWeb.MixProject do
7 7
       app: :elixir,
8 8
       version: "0.0.1",
9 9
       elixir: "~> 1.7",
10
+      elixirc_paths: elixirc_paths(Mix.env()),
10 11
       start_permanent: Mix.env() == :prod,
11 12
       description: @description,
12 13
       package: package(),
@@ -25,7 +26,9 @@ defmodule IndieWeb.MixProject do
25 26
   defp deps do
26 27
     [
27 28
       {:ex_doc, "~> 0.14", only: :dev},
28
-      {:microformats2, "~> 0.2.0"}
29
+      {:microformats2, "~> 0.2.0"},
30
+      {:exvcr, "~> 0.10", only: :test},
31
+      {:faker, "~> 0.12.0", only: :test},
29 32
     ]
30 33
   end
31 34
 
@@ -36,4 +39,8 @@ defmodule IndieWeb.MixProject do
36 39
       links: %{"Source Code" => "https://git.jacky.wtf/indieweb/elixir"}
37 40
     ]
38 41
   end
42
+
43
+
44
+  defp elixirc_paths(:test), do: ["lib", "test/support"]
45
+  defp elixirc_paths(_), do: ["lib"]
39 46
 end

+ 12
- 0
mix.lock View File

@@ -1,7 +1,19 @@
1 1
 %{
2 2
   "earmark": {:hex, :earmark, "1.3.1", "73812f447f7a42358d3ba79283cfa3075a7580a3a2ed457616d6517ac3738cb9", [:mix], [], "hexpm"},
3 3
   "ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
4
+  "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm"},
5
+  "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"},
6
+  "exvcr": {:hex, :exvcr, "0.10.3", "1ae3b97560430acfa88ebc737c85b2b7a9dbacd8a2b26789a19718b51ae3522c", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
7
+  "faker": {:hex, :faker, "0.12.0", "796cbac868c86c2df6f273ea4cdf2e271860863820e479e04a374b7ee6c376b6", [:mix], [], "hexpm"},
8
+  "floki": {:hex, :floki, "0.20.4", "be42ac911fece24b4c72f3b5846774b6e61b83fe685c2fc9d62093277fb3bc86", [:mix], [{:html_entities, "~> 0.4.0", [hex: :html_entities, repo: "hexpm", optional: false]}, {:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
9
+  "html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], [], "hexpm"},
10
+  "httpotion": {:hex, :httpotion, "3.1.1", "b8ad199dea2c56a70c89e7f9e4d09898c7e85871783b7417c04cb4f1d4d8e919", [:mix], [{:ibrowse, "== 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: false]}], "hexpm"},
11
+  "ibrowse": {:hex, :ibrowse, "4.4.0", "2d923325efe0d2cb09b9c6a047b2835a5eda69d8a47ed6ff8bc03628b764e991", [:rebar3], [], "hexpm"},
12
+  "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"},
4 13
   "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
5 14
   "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
15
+  "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"},
16
+  "microformats2": {:hex, :microformats2, "0.2.1", "452e8749566500ea70fcaa9b5680b00a20803aa8d1e490f8f84ae3c38a30799a", [:mix], [{:floki, "~> 0.7", [hex: :floki, repo: "hexpm", optional: false]}, {:httpotion, "~> 3.0", [hex: :httpotion, repo: "hexpm", optional: false]}], "hexpm"},
17
+  "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
6 18
   "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"},
7 19
 }

+ 0
- 8
test/indieweb_test.exs View File

@@ -1,8 +0,0 @@
1
-defmodule IndieWebTest do
2
-  use ExUnit.Case
3
-  doctest IndieWeb
4
-
5
-  test "greets the world" do
6
-    assert IndieWeb.hello() == :world
7
-  end
8
-end

+ 9
- 0
test/support/case.ex View File

@@ -0,0 +1,9 @@
1
+defmodule IndieWeb.TestCase do
2
+  use ExUnit.CaseTemplate
3
+
4
+  using do
5
+    quote do
6
+      use ExUnit.Case
7
+    end
8
+  end
9
+end

+ 5
- 0
test/support/http.ex View File

@@ -0,0 +1,5 @@
1
+defmodule IndieWeb.Test.HttpAdapter do
2
+  defdelegate request(uri, methods, opts), to: IndieWeb.Http.Adapters.HTTPotion
3
+end
4
+
5
+Application.put_env(:indieweb, :http_adapter, IndieWeb.Test.HttpAdapter, persistent: true)

+ 5
- 0
test/test_helper.exs View File

@@ -1 +1,6 @@
1 1
 ExUnit.start()
2
+
3
+ExUnit.configure(
4
+  exclude: [slow: true, skip: true],
5
+  formatters: [ExUnit.CLIFormatter]
6
+)

+ 40
- 0
test/unit/indieweb/http_test.exs View File

@@ -0,0 +1,40 @@
1
+defmodule IndieWeb.HttpTest do
2
+  use IndieWeb.TestCase, async: false
3
+  use ExVCR.Mock
4
+  alias IndieWeb.Http, as: Subject
5
+  doctest Subject
6
+
7
+  setup do
8
+    Application.put_env(:indieweb, :http_adapter, IndieWeb.Test.HttpAdapter, persistent: true)
9
+    :ok
10
+  end
11
+
12
+  describe ".adapter/0" do
13
+    test "pulls the one defined in configuration" do
14
+      Application.put_env(:indieweb, :http_adapter, IndieWeb.Test.HttpAdapter, persistent: true)
15
+      assert Subject.adapter() == IndieWeb.Test.HttpAdapter
16
+    end
17
+
18
+    test "defaults to using HTTPotion" do
19
+      Application.delete_env(:indieweb, :http_adapter)
20
+      assert Subject.adapter() == IndieWeb.Http.Adapters.HTTPotion
21
+    end
22
+  end
23
+
24
+  describe ".request/2" do
25
+    test "successfully sends a HTTP GET request by default" do
26
+      use_cassette :stub, [uri: "~r/*", method: :get] do
27
+        assert {:ok, %IndieWeb.Http.Response{code: 200}} = Subject.request("https://indieweb.org")
28
+      end
29
+    end
30
+
31
+    for method <- ~w(get post options head put patch delete)a do
32
+      test "successfully sends a HTTP #{method} request" do
33
+
34
+        use_cassette :stub, [uri: "~r/*", method: unquote(method)] do
35
+          assert {:ok, %IndieWeb.Http.Response{}} = Subject.request("https://indieweb.org", unquote(method))
36
+        end
37
+      end
38
+    end
39
+  end
40
+end

Loading…
Cancel
Save