API управления версиями в Elixir Plug - PullRequest
1 голос
/ 11 июля 2019

У меня есть два модуля: lib / endpoints / v1 / base.ex и lib / endpoints / v2 / base.ex.

lib / endpoints / v1 / base.ex

defmodule Http.Endpoints.V1.Base do
  require Logger
  use Plug.Router

  plug(:match)
  plug(:dispatch)
  plug(Plug.Logger)
  plug(Plug.Parsers, parsers: [:json], json_decoder: Poison)

  get "/v1/ping" do
    send_resp(conn, 200, "pong!")
  end
end

lib / endpoints / v2 / base.ex

defmodule Http.Endpoints.V2.Base do
  require Logger
  use Plug.Router

  plug(:match)
  plug(:dispatch)
  plug(Plug.Logger)
  plug(Plug.Parsers, parsers: [:json], json_decoder: Poison)

  get "/v2/ping" do
    send_resp(conn, 200, "pong! 2")
  end
end

Моя конечная точка работает правильно, если я добавляю свои приложения .ex дочерние элементы

Plug.Cowboy.child_spec(scheme: :http, plug: Http.Endpoints.V1.Base, options: [port: Application.get_env(:http, :port)])

Но я бы хотел, чтобы мое приложение запускало все версии конечных точек.

Я попытался создать lib / endpoints.ex с require Http.Endpoints.V1.Base и require Http.Endpoints.V2.Base и изменил свои приложения.бывший, но это не сработало.

Ответы [ 2 ]

5 голосов
/ 11 июля 2019

Вы можете пересылать на другие маршрутизаторы из файла конечных точек.Вот документация для функции forward/2: https://hexdocs.pm/plug/Plug.Router.html#forward/2

В основном вы создаете 2 маршрутизатора для v1 и v2:

defmodule MyAppWeb.V2.Router do
  use Plug.Router

  get "/ping" do
    send_resp(conn, 200, "OK")
  end
end

и

defmodule MyAppWeb.V1.Router do
  use Plug.Router

  get "/ping" do
    send_resp(conn, 200, "OK")
  end
end

Тогдав вашей конечной точке вы можете добавить все обычные функции и переслать в ваши версионные маршруты, например, так:

defmodule MyAppWeb.Endpoint do
  require Logger
  use Plug.Router

  plug(:match)
  plug(:dispatch)
  plug(Plug.Logger)
  plug(Plug.Parsers, parsers: [:json], json_decoder: Poison)

  # Forwarding
  forward "/v2", to: MyApp.V2.Router
  forward "/v1", to: MyApp.V1.Router

  # You should put a catchall here
  match _ do
    send_resp(conn, 404, "Not Found")
  end
end

Затем в вашем файле application.ex смонтируйте конечную точку, как вы это делали раньше.Однако на этом этапе вы сможете пропинговать /v1/ping и /v2/ping с одного и того же порта.

Cheers!

1 голос
/ 12 июля 2019

Моя конечная точка работает правильно, если я добавляю свои приложения. Например, дети

Plug.Cowboy.child_spec(
   scheme: :http, 
   plug: Http.Endpoints.V1.Base, 
   options: [port: Application.get_env(:http, :port)]
)

Современный способ указать это:

{Plug.Cowboy, [[ 
      scheme: :http, 
      plug: Http.Endpoints.V1.Base, 
      options: [port: Application.get_env(:http, :port)]
    ]]
}

См.: https://hexdocs.pm/elixir/Supervisor.html#module-child_spec-1

Хотя мне кажется, что проще вызвать child_spec() напрямую, чем пытаться определить, сколько скобок нужно вокруг аргумента.

...