Config url: [path: "/my_path"] not honored in Router endpoints?

Greetings folks, hope this question finds you well.

There’s reasonable likelihood I glossed over something in the documentation, but I’m not able to assemble my query in such a way as to easily come up with the answer.

I’m attempting to utilize runtime.exs to dynamically assign my Endpoint's :url's path:, but am getting tripped up either in other configuration or my understanding of how it should work.

For example, if I’ve configured the path: to be "/my_path", I would expect everything in my Router to get “/my_path” prefixed to it, however, that’s simply not the case. I would, for example, expect "/" to handle requests for /my_path/ (the index), but that’s not the case.

Any help would be very much appreciated!

Is it idiomatic to have a Plug that inspects for presence of the configured :path and strips it off if found?

This is basically the recipe defined here Subdomains With Phoenix - Gazler, but that being from 2015 I’m curious if some other approach has become generally accepted.

thanks for looking

I’d like to clarify what I’m attempting. It’s effectively the exact treatment FastAPI’s root_path provides: Behind a Proxy - FastAPI

The phoenix app runs in a container behind nginx and nginx will be rewriting the url to include a distinguishing prefix. The goal here is to not need to change my code depending on whether it’s being run behind nginx or not based on an environment variable. So for example if I’ve got a route of /cool/stuff I’d love for it to also be able to field /nginx_prefix/cool/stuff if it happened to be running that way and said environment variable specified /nginx_prefix.

This is maddening… please, please help!

It would be much easier to answer if you gave example code. Right now I can only guess your approach. So some vague suggestions:

  • you use the work “dynamic” - you can’t change how code runs through runtime.exs while the server is running. runtime.exs is run when the server starts just once.
  • how are you setting the path exactly? Here’s an example of setting the path from my own project:
config :chat5g, Chat5gWeb.Endpoint,
  url: [host: "localhost", port: 4000, path: System.get_env("SUB_PATH")],
  server: true,

would also help if you specified the error or other symptom to why you think it’s not working.

also - welcome to the forums :slight_smile:

It’s very similar to your example. Again, I very well may be presuming something and it simply doesn’t reflect reality.

  host = System.get_env("PHX_HOST") || "localhost"
  port = String.to_integer(System.get_env("PORT") || "8000")
  path_prefix = System.get_env("PATH_PREFIX") || "/"

  config :offerings, OfferingsWeb.Endpoint,
    url: [host: host, port: port, path: path_prefix],
    http: [
      # Enable IPv6 and bind on all interfaces.
      # Set it to  {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
      # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
      # for details about using IPv6 vs IPv4 and loopback vs public addresses.
      ip: {0, 0, 0, 0, 0, 0, 0, 0},
      port: port
    ]

Is it not reasonable with that to believe a route configured to / would automagically work for /nginx_prefix/ if the PATH_PREFIX env value was set to /nginx_prefix? What am I missing??

Oh, btw, that’s from runtime.exs

thanks!

that is a reasonable assumption. still need to know:

  1. how are you setting PATH_PREFIX? Maybe try with a hardcoded value first.
  2. are you starting with mix phx.server? if not you need server: true
  3. please describe expected outcome and actual. i fail to understand what exactly is not performing as expected.

how are you setting PATH_PREFIX? Maybe try with a hardcoded value first.

Two ways, depending on how the app gets run: -e if through docker run and simple export if using by way of release. The runtime config is picking it up and internal links are getting the prefix treatment, however, clicking those links don’t get served by the route.

are you starting with mix phx.server? if not you need server: true

Thanks, but that’s not the issue; the release is working as expected, just not the root path stuff

please describe expected outcome and actual. i fail to understand what exactly is not performing as expected.

Environment variable, as outlined above, is set to /nginx_prefix. Expected outcome of localhost:4000/nginx_prefix/ is to bring up the default Phoenix index page.

Actual outcome is http 404 “Not found”

The index page is provided at localhost:4000 and its link to LiveDashBoard is given :path treatment such that its link is localhost:4000/nginx_prefix/dashboard, but that too yields a 404 “Not found”

Is the expectation that when using :path that the reverse proxy strips that off?

The docs say (emphasis is mine):

:url - configuration for generating URLs throughout the app. Accepts the :host , :scheme , :path and :port options. All keys except :path can be changed at runtime.

Which states that the configuration is only used with generating URLs, not when routing.

Thanks, Kip, I did read those docs prior to posting, but didn’t take it quite so literally that it was only generating, rather than having additional outward effect on the routes. As such, it appears the answer to my question about the reverse proxy stripping off the :path value is correct, assuming the intent is to have reverse proxy agnostic routes.

FWIW, the link I previously provided for that Python framework does indeed decorate endpoints with a prefix. Nevertheless, hopefully anyone else confused by the somewhat nebulous docs will find this of value.

thanks!

Sometimes you get an idea in your head and it’s just simply not correct. The Python framework functionality I mentioned works similarly to :path link generation. I was thinking I’d edit that, but it appears it’s no longer an option.