Reputation: 487
I have two modules: lib/endpoints/v1/base.ex and 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
My endpoint works correctly if I put in my applications.ex the children
Plug.Cowboy.child_spec(scheme: :http, plug: Http.Endpoints.V1.Base, options: [port: Application.get_env(:http, :port)])
But I would like my application starts all endpoints versions.
I tried to create lib/endpoints.ex with require Http.Endpoints.V1.Base
and require Http.Endpoints.V2.Base
and changed my applications.ex but it did not work.
Upvotes: 3
Views: 275
Reputation: 2882
You can forward to other routers from your endpoints file. Here is the documentation for the forward/2
function: https://hexdocs.pm/plug/Plug.Router.html#forward/2
Basically you create 2 routers for v1 & v2:
defmodule MyAppWeb.V2.Router do
use Plug.Router
plug :match
plug :dispatch
get "/ping" do
send_resp(conn, 200, "OK")
end
end
and
defmodule MyAppWeb.V1.Router do
use Plug.Router
plug :match
plug :dispatch
get "/ping" do
send_resp(conn, 200, "OK")
end
end
Then in your endpoint you can add all the common functionality and forward to your versioned routes like so:
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 catch-all here
match _ do
send_resp(conn, 404, "Not Found")
end
end
Then in your application.ex
file, mount your endpoint as you did before. However, at this point you should be able to ping both /v1/ping
and /v2/ping
from the same port.
Cheers!
Upvotes: 6
Reputation: 48599
My endpoint works correctly if I put in my applications.ex the children
Plug.Cowboy.child_spec( scheme: :http, plug: Http.Endpoints.V1.Base, options: [port: Application.get_env(:http, :port)] )
The modern way to specify that is:
{Plug.Cowboy, [[
scheme: :http,
plug: Http.Endpoints.V1.Base,
options: [port: Application.get_env(:http, :port)]
]]
}
See: https://hexdocs.pm/elixir/Supervisor.html#module-child_spec-1
Although, to me it seems easier to call child_spec()
directly, rather than try to figure how many brackets you need around the argument.
Upvotes: 1