So I’m writing a lib to wrap an API. The external API implements webhooks, which I want my lib to intercept and handle. Would it make more sense to put a plug in the projects endpoint, or a macro that creates a route in the router?
plug MyLib.Webhooks, url: "/webhooks", handler: fn event -> IO.puts(event) end
use MyLib.Webhooks, url: "/webhooks", handler: fn event -> IO.puts(event) end
In the plug version I would match the route (what’s the best way to do this?), and then call the handler, then halt the conn
use version I would write a macro that creates a route based on the given webhook url.
Which one of these is better practice? Why?
I’d write a single plug that users put in their routers or anywhere else themselves. So I’d go with the first approach.
I would also put my vote on a Plug since that gonna be more flexible and less magical.
If I use a plug, what’s the best way to determine if a incoming plug is one that should be handled or not? I can’t find a function in Phoenix.Router that says if a conn matches a route.
You can probably use
conn.path_info and compare it with whatever is passed in
defmodule YourPlug do
def call(conn, opts) do
url = opts[:url] # "/webhooks" in your example
case conn.path_info do
[^url] -> # match
_unmatched -> # no match
Ideally though, you shouldn’t care about this and leave it to the user, they would use
forward macro when appropriate:
defmodule UsersRouter do
forward "/webhook", to: YourPlug
I’d look at
:absinthe_plug for inspiration.
forward makes a lot more sense than what I was trying to do with the Plug taking a path and matching it against the Conn. Thank you!