Serving Phoenix LiveView application on a subdirectory

We have a Phoenix application that makes extensive use of LiveView. A little background about the deployment situation:

  • It’s installed locally on the customer’s server, and they access it at a subdirectory of their machine, through a custom IIS site (this is all on Windows)

  • For example, the app itself might run on http://localhost:4200, and the user would access it at http://myserver.local/subdirectory/real-application

  • We use the IIS URL rewrite module to get everything after the subdirectory and give it to the “real” server, so in theory the Phoenix app shouldn’t have to worry about the subdirectory.

  • We don’t know the subdirectory at compile time.

The problem comes when connecting to the LiveView server. On mount the LiveView JavaScript module uses window.location.href to get the current URI from the browser, and then sends it to the server. From there, it’s decoded using the URI module and passed to Phoenix.Router.route_info/3. This function tries to match the URL to a route defined in router.ex. However, since the URL being passed is fetched using the browser API (in this example, it would be http://myserver.local/subdirectory/real-application), the call fails since it’s obviously not a real route.

The exact error we get is:

cannot invoke handle_params nor live_redirect/live_link to <url> because it isn't defined in <router>.

This is thrown from Phoenix.LiveView.Utils.live_link_info!/3 , which itself is called from Phoenix.LiveView.Channel.verified_mount/4. We’ve tried modifiying the LiveView source code, allowing a different URL to be passed to the server on mount. This stops the error above, but the connection still isn’t properly made.

We’re a little lost on how to solve this, so it would be great if someone could give us some tips :smiley:

i had a similar problem when trying to include a live-view as an embeddable widget on an any page of an arbitrary external CMS.

i solved it like this in app.js:

class MyLiveSocket extends LiveSocket {

  getHref() {
    let href=super.getHref(); 
    // ... manipulate href to your liking
    return href;
  }

}

...

let liveSocket = new MyLiveSocket("/live", Socket, {

3 Likes