When building APIs or proxy-style endpoints in Phoenix, you might occasionally need a single route to handle multiple HTTP methods - like GET
, POST
, PUT
, DELETE
, and even OPTIONS
.
While Phoenix typically uses one macro per method (e.g., get
, post
), there's a lesser-known match/5
macro that gives you more flexibility.
Phoenix’s match/5
macro allows you to define a route that responds to multiple HTTP verbs:
# router.ex
match :*, "/api/endpoint", MyAppWeb.APIController, :handle
This line tells Phoenix to route any of the listed HTTP methods on /api/endpoint
to APIController.handle/2
.
A common scenario is handling CORS preflight requests (OPTIONS
) in combination with other CRUD operations on the same path:
defmodule MyAppWeb.APIController do
use MyAppWeb, :controller
def handle(conn, _params) do
case conn.method do
"OPTIONS" ->
conn
|> put_resp_header("access-control-allow-origin", "*")
|> put_resp_header("access-control-allow-methods", "GET,POST,PUT,DELETE,OPTIONS")
|> send_resp(204, "")
"GET" ->
json(conn, %{message: "This is a GET request"})
"POST" ->
json(conn, %{message: "Data created"})
"PUT" ->
json(conn, %{message: "Data updated"})
"DELETE" ->
json(conn, %{message: "Data deleted"})
_ ->
send_resp(conn, 405, "Method Not Allowed")
end
end
end
Pros
- One controller action for all methods
- Useful for generic APIs, CORS handling, and proxies
Cons
- Less idiomatic than Phoenix’s standard RESTful routes
- Controller action becomes more complex
- No compile-time route method checks
The match/5
macro is a powerful tool when you need flexibility in routing HTTP methods. Use it carefully—it's not a replacement for conventional RESTful design, but it's perfect for those cases where the router needs to get out of your way.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.