rogerweb
Hi,
I’m running a Phoenix application behind a AWS ALB (Application Load Balancer), which routes requests to different applications based on the path in the requested URL.
Requests that start with /myapp are routed to my application.
The problem is that ALB doesn’t support stripping this /myapp prefix from the actual URL that goes to Phoenix (differently from nginx, haproxy, etc) and I wouldn’t like to add this prefix (a deployment configuration) to all my routes as it can only be done in compilation time (at least without having to create a router myself which I think would be overkill; I might be wrong though).
In an attempt to overcome this issue, I’ve created a simple plug that runs before everything and removes the prefix from connection’s path_info. For instance, it turns
["myapp", "assets", "app-978a7188b69b3752fe7c58e50c7e5571.js"]
into
["assets", "app-978a7188b69b3752fe7c58e50c7e5571.js"]
Also, I configure my Endpoint to use this prefix as the path so URLs generated by the application include the prefix back and are properly routed by ALB.
# runtime.exs
config :myapp, MyAppWeb.Endpoint,
url: [
host: get_env("PHX_HOST", "localhost"),
port: get_env("PHX_PORT", 4000, :int),
path: get_env("PHX_PATH", "/") # get_env is just a helper func
]
It works fine for assets and regular routes, but not for sockets and anything that uses sockets like live reloading and the dashboard. Example:
17:39:09.218 [info] GET /myapp/socket/websocket
17:39:09.280 [debug] ** (Phoenix.Router.NoRouteError) no route found for GET /socket/websocket (MyAppWeb.Router)
(myapp 1.0.0-alpha.19) lib/phoenix/router.ex:405: MyAppWeb.Router.call/2
(myapp 1.0.0-alpha.19) lib/myapp_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
The plug feels like a hack and it didn’t solve my problem.
Have you guys had to deal with a similar deployment? How did you manage?
Cheers!
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixir-ls
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Exadra37
If your app deployment target for production is to be behind that aws load balancer why do you want to overcome the issue in your app? Why not keeping it simple and just add the prefix?
Doesn’t the load balancer support to invoke a lambda function?
Or if your domain is with Route53 you can try to use forwarding rules:
rogerweb
Thanks @Exadra37 for taking the time to read my post, I really appreciate it.
I don’t
I just don’t know how.
Add the prefix where? To my application’s router
scope’s ?It does. Not sure how it would help specially because my app uses websockets.
It is not but I have no problems moving to it if it solves the issue. I’m not sure though as I think DNS usually doesn’t get involved with URL paths, right?
Exadra37
Yes, and in the sockets configuration on the endpoint module.
Read the link I shared.
rogerweb
Because the prefix is a deployment-specific configuration. I should not need to re-compile the application to change it.
Also, it breaks Phoenix’s LiveDashboard (it adds the prefix twice to the URL) and live reload (dev only):
I will. Thanks again.
Exadra37
You didn’t mention that was deployment specific. But you may try to read the prefix from the runtime.exs configuration, thus no need to recompile the app, only needs to setup an env var with the prefix.
Where is it in the logs?
Please add your router file to your first post so we can better understand what you are doing.
rogerweb
That’s what I do for all my runtime configuration and that was my first attempt before starting this thread, but I soon realized that the
scopein Phoenix’s router is evaluated at compilation time. So I can’t use things likeApplication.fetch_env!(:myapp, :prefix).If I do like:
I correctly get a compilation error:
I couldn’t figure out how to edit my original post so here it goes.
Router with all the routes statically prefixed with the “/myapp”:
You didn’t ask but I guess the Endpoint is also relevant as the sockets are defined there:
Endpoint with all the sockets statically prefixed with the “/myapp”:
Note 1: I tried with
socket "/myapp/phoenix/live_reload/socket"too but it doesn’t work either.Exadra37
I though that could be the case after I suggested it.
Sorry for the misleading tip but my Elixir experience is limited to toy apps, thus I am not yet very fluent on it yet.
after some time elapses we cannot edit it any-more.
You also need to update
assets/js/app.js:derek-zhou
Don’t do that. all you need to do are:
urlkey of your Endpoint config with a non-root url.<body>tag to pass the correct url (derived from above) to the client siderogerweb
Hi Derek, thanks for joining the conversation.
When you say “Don’t do that” what are you referring to?
I understand your suggestion is the standard approach when the load balancer can re-write the URL, which unfortunately is not the case:
So the request reaches the router with the prefix, hence it is not found.
derek-zhou
With
urlconfig in place, every request reaching plug would need to have the prefix to be processed. So, you need to add the prefix for the socket connect, as the standard js from a phx.new don’t have it. This is my second point.I am not sure about AWS ALB, but this is how multiple phoenix apps work behind a single nginx reverse proxy.