Plug.Logger placement in endpoint.ex vs router.ex

I have a logger metadata plug (MyAppWeb.Plug.LoggerMetadata) that requires the following 2 plugs to run first in order to add the user_id to the metadata:

  • plug(:fetch_session)
  • plug(MyAppWeb.Auth.Pipeline) (which uses Guardian to fetch the user_id)

So I initially set up the endpoint.ex file to look like this:

  ....
  plug(:fetch_session)
  plug MyAppWeb.Auth.Pipeline
  plug MyAppWeb.Plug.LoggerMetadata
  plug(Plug.Logger)

  plug(MyAppWeb.Router)
  ...

It feels weird to have fetch_session and Auth.Pipeline in endpoint.ex as opposed to the router, though.

So I ended up moving those plugs back to the router.ex file like so:

...
pipeline :logger do
  plug MyAppWeb.Plug.LoggerMetadata
  plug(Plug.Logger)
end

pipeline :support_authentication do
  plug(MyAppWeb.Auth.Pipeline)
end

pipeline :browser do
  plug(:accepts, ["html"])
  plug(:fetch_session)
  plug(:support_authentication)
  plug(:logger)
  ...
end
...

This also feels weird because now we have to explicitly call the logger with each new pipeline such as api, ajax, etc.

I’m wondering if there are any drawbacks/gotchas with my first method or maybe if I’m missing some third option.

Do you want that user_id be available in both messages of Plug.Logger? If yes, then unfortunately this is probably the only solution, if it is enough to have that message only in second message, then you can put Plug.Logger back to the endpoint.

1 Like

The Endpoint is all about what is requisite for an HTTP request to connect to your service.

The Router is about which controller to connect to given certain request values.

The point of a pipeline is to sort of blur the difference in your Router (in a useful way!) with nuanced controls based on request metadata: you don’t want to deny the request outright, you just want to pre-process it (and maybe choose to reject it with an appropriate status code) based on processing.

In this lens, auth belongs in the pipelines in your Router. Where an Endpoint should refuse responses outright, you probably want your Router to return meaningful auth failure HTTP status codes to callers.

Specifically, you want to route a request to a particular unauthenticated response: definitely a Router concern. I think your idea of making auth support a discrete pipeline makes sense in this context.

1 Like