diff --git a/lib/uplink/cache/router.ex b/lib/uplink/cache/router.ex index 0473b4b..30ec5b5 100644 --- a/lib/uplink/cache/router.ex +++ b/lib/uplink/cache/router.ex @@ -4,6 +4,7 @@ defmodule Uplink.Cache.Router do alias Uplink.Secret alias Uplink.Cache + alias Uplink.Routings plug :match @@ -23,4 +24,15 @@ defmodule Uplink.Cache.Router do json(conn, :ok, %{message: "cache key :self deleted."}) end + + delete "/routers/:router_id/proxies" do + router_id = String.to_integer(router_id) + + Cache.transaction([keys: [{:proxies, router_id}]], fn -> + Cache.delete({:proxies, router_id}) + Routings.list_proxies(router_id) + end) + + json(conn, :ok, %{message: "cache key {:proxies, #{router_id}} refreshed."}) + end end diff --git a/lib/uplink/web.ex b/lib/uplink/web.ex index cb48eff..f22eda6 100644 --- a/lib/uplink/web.ex +++ b/lib/uplink/web.ex @@ -4,7 +4,7 @@ defmodule Uplink.Web do def json(conn, status, response) do conn |> put_resp_header("content-type", "application/json") - |> send_resp(status, Jason.encode!(%{data: response})) + |> send_resp(status, Jason.encode_to_iodata!(%{data: response})) end def redirect(conn, location) do diff --git a/test/uplink/cache/router_test.exs b/test/uplink/cache/router_test.exs index ff69f11..bf0d669 100644 --- a/test/uplink/cache/router_test.exs +++ b/test/uplink/cache/router_test.exs @@ -1,5 +1,5 @@ defmodule Uplink.Cache.RouterTest do - use ExUnit.Case, async: true + use ExUnit.Case use Plug.Test alias Uplink.Cache.Router @@ -16,12 +16,20 @@ defmodule Uplink.Cache.RouterTest do describe "delete self" do setup do + bypass = Bypass.open() + + Application.put_env( + :uplink, + Uplink.Clients.Instellar, + endpoint: "http://localhost:#{bypass.port}/uplink" + ) + signature = :crypto.mac(:hmac, :sha256, Uplink.Secret.get(), @valid_delete_body) |> Base.encode16() |> String.downcase() - {:ok, signature: signature} + {:ok, signature: signature, bypass: bypass} end test "can successfully delete :self", %{signature: signature} do @@ -33,5 +41,46 @@ defmodule Uplink.Cache.RouterTest do assert conn.status == 200 end + + test "can successfully delete {:proxies, router_id}", %{ + signature: signature, + bypass: bypass + } do + Bypass.expect_once( + bypass, + "GET", + "/uplink/self/routers/1/proxies", + fn conn -> + conn + |> Plug.Conn.put_resp_header("content-type", "application/json") + |> Plug.Conn.send_resp( + 200, + Jason.encode_to_iodata!(%{ + "data" => [ + %{ + "attributes" => %{ + "id" => 1, + "router_id" => 1, + "hosts" => ["opsmaru.com", "www.opsmaru.com"], + "paths" => ["/how-to*"], + "tls" => true, + "target" => "proxy.webflow.com", + "port" => 80 + } + } + ] + }) + ) + end + ) + + conn = + conn(:delete, "/routers/1/proxies", @valid_delete_body) + |> put_req_header("x-uplink-signature-256", "sha256=#{signature}") + |> put_req_header("content-type", "application/json") + |> Router.call(@opts) + + assert conn.status == 200 + end end end diff --git a/test/uplink/clients/caddy/config/builder_test.exs b/test/uplink/clients/caddy/config/builder_test.exs index 9707fe2..16e996a 100644 --- a/test/uplink/clients/caddy/config/builder_test.exs +++ b/test/uplink/clients/caddy/config/builder_test.exs @@ -361,7 +361,7 @@ defmodule Uplink.Clients.Caddy.Config.BuilderTest do |> Plug.Conn.put_resp_header("content-type", "application/json") |> Plug.Conn.send_resp( 200, - Jason.encode!(%{ + Jason.encode_to_iodata!(%{ "data" => [ %{ "attributes" => %{ diff --git a/test/uplink/routings/proxy/manager_test.exs b/test/uplink/routings/proxy/manager_test.exs new file mode 100644 index 0000000..8d32316 --- /dev/null +++ b/test/uplink/routings/proxy/manager_test.exs @@ -0,0 +1,54 @@ +defmodule Uplink.Routings.Proxy.ManagerTest do + use ExUnit.Case + + alias Uplink.Cache + alias Uplink.Routings + + setup do + bypass = Bypass.open() + + Application.put_env( + :uplink, + Uplink.Clients.Instellar, + endpoint: "http://localhost:#{bypass.port}/uplink" + ) + + {:ok, bypass: bypass} + end + + describe "list proxies" do + test "fetch and parse proxies", %{bypass: bypass} do + Cache.delete({:proxies, 1}) + + Bypass.expect_once( + bypass, + "GET", + "/uplink/self/routers/1/proxies", + fn conn -> + conn + |> Plug.Conn.put_resp_header("content-type", "application/json") + |> Plug.Conn.send_resp( + 200, + Jason.encode_to_iodata!(%{ + "data" => [ + %{ + "attributes" => %{ + "id" => 1, + "router_id" => 1, + "hosts" => ["opsmaru.com", "www.opsmaru.com"], + "paths" => ["/how-to*"], + "tls" => true, + "target" => "proxy.webflow.com", + "port" => 80 + } + } + ] + }) + ) + end + ) + + assert [%Routings.Proxy{} = _proxy] = Routings.list_proxies(1) + end + end +end