Best practice? Making a route available only in dev/staging environments

I’m working on building a GraphQL API using Phoenix. For now, we have the Graphiql browser IDE set up on its own dedicated route so other developers and front-end guys can inspect the API. However, on prod, I don’t think we want this route visible. We could come up with a firewall or something, but I’m wondering if there is any way to avoid declaring that route when the env is prod. I feel like any if-statements around environment are smelly and make testing more difficult. However, I don’t want to expose this either.

Anyone have any thoughts on this? Thanks!

1 Like

Not the answer you may be looking for but at work we just restrict the /graphiql route to users that are logged in as company admins which you can accomplish with a simple plug. Plus graphiql doesn’t really expose anything that isn’t already exposed via the GraphQL api itself.

1 Like

:wave:

You can add this instead to your router

if Mix.env == :dev do
  forward "/graphiql",
    to: Absinthe.Plug.GraphiQL,
    init_opts: [schema: MyAppWeb.Schema]
end

That is, if you are using Mix with development environment under staging. Once you compile with prod this section will not be included on your routing.

Hope that helps

3 Likes

The Mix.env trick does not work anymore when working with a mix release build. I even tried replacing this with checking a System.get_env but it does not work since routes.ex seems to bee compiled and expanded from its macro form at compile time.

In case anyone is searching in the future, I found another answer for this:

  1. Add some kind of environment setting in your various config files (dev.exs, prod.exs, test.exs):
  config :my_app, :environment, :prod
  1. In your router (and in my case, nav code in templates) you can then inspect that setting
  if Application.get_env(:my_app, :environment) in [:dev, :test] do
    ...

seems to work ok - I have checked running using mix & a release.

2 Likes

This approach works, but consider using a specific key in config like config :my_app, :whatever_the_feature_is_called and enabling / disabling that in files like config/test.exs etc - coupling everything to a generic “environment” option makes it harder to see what options vary per-environment.

4 Likes

I can confirm this is a better way! My approach got convoluted quickly and I soon switched to yours.

1 Like