temporalio/ui

Support serving UI under subdomain

gregbrowndev opened this issue · 1 comments

Describe the bug

Link to Slack thread where I originally asked this question.

I want to host the Temporal UI at the root path of a subdomain, e.g. temporal.[mydomain].com, using host-based routing in ALB.

This is important because I can't avoid subdomains in the URL, even if I hosted the UI at a specific path, e.g. [mydomain].com/temporal, since I also have a staging environment where the UI will be hosted at staging.[mydomain].com/temporal.

When I configure host-based routing in ALB to route temporal.[mydomain].com to the frontend service, I have two options to configure the frontend service.

  1. With TEMPORAL_UI_PUBLIC_PATH=/, the page fails to fetch the JS resources in the browser because the HTML returned from the server contains // in front of the JS bundles, e.g.
<link rel="modulepreload" href="//_app/immutable/entry/start.XNU22-I9.js"> 

This tells the browser to ignore the same origin rule, and the requests instead get sent to https://_app/immutable/entry/start.XNU22-I9.js which doesn't exist.

  1. With TEMPORAL_UI_PUBLIC_PATH=temporal.[mydomain].com, now the UI can fetch the bundles linked in the HTML, but then fails to load the JS.

E.g. this file temporal.[mydomain].com]/_app/immutable/entry/start.XNU22-I9.js contains:

import{c as a}from"../chunks/entry.npYmAy9v.js";export{a as start};

The referenced file does exist and contains a load of JS, if I go to it directly, i.e. temporal.[mydomain].com/_app/immutable/chunks/entry.npYmAy9v.js. But it fails to load in the browser:

(index):26 Uncaught (in promise) TypeError: Failed to resolve module specifier 'temporal.[mydomain].com/_app/immutable/entry/start.XNU22-I9.js'
    at (index):26:14

To Reproduce
Steps to reproduce the behavior:

  1. Host Temporal Frontend service (I've got it on ECS) with TEMPORAL_UI_PUBLIC_PATH=/
  2. Configure load balancer to forward requests matching the host and path, e.g. with ALB listener rule:
  condition {
    host_header {
      values = ["temporal.${local.domain_name}"]
    }
  }

  condition {
    path_pattern {
      values = [
        "/*",
      ]
    }
  }
  1. Visit Temporal UI in the browser, e.g. https://temporal.[mydomain].com

Expected behavior

The frontend SPA should respect the same origin rule and fetch resources from TEMPORAL_UI_PUBLIC_PATH on the same domain (including subdomains) it originated.

Screenshots

N/a

Desktop (please complete the following information):

  • OS: MacOS 14.6 (23G80)
  • Browser: Version 127.0.6533.89 (Official Build) (arm64)

Additional context

N/A

OK I've figured it out. You can deploy on a subdomain, but setting TEMPORAL_UI_PUBLIC_PATH=/ completely breaks the UI. Leaving the env var unset fixes the issue.

The reason this breaks the deployment is because setting the TEMPORAL_UI_PUBLIC_PATH=/ causes the HTML to render the link tags in the HTML meta with an extra /.

The ui-server project contains the links in question that fetch the JS bundles. If you set the public path, what actually gets rendered is:

		<link rel="modulepreload" href="//_app/immutable/entry/start.PkAQ5dFz.js">
		<link rel="modulepreload" href="//_app/immutable/chunks/entry.wLcqREKA.js">
		<link rel="modulepreload" href="//_app/immutable/chunks/scheduler.1T9hOnFr.js">
		<link rel="modulepreload" href="//_app/immutable/chunks/paths.IPjQg0PU.js">
		<link rel="modulepreload" href="//_app/immutable/chunks/control.pJ1mnnAb.js">
		<link rel="modulepreload" href="//_app/immutable/entry/app.2gko0slu.js">
		<link rel="modulepreload" href="//_app/immutable/chunks/index.cVovwi_s.js">

Which tells the browser to ignore the same origin hostname completely and fetch the resources as:

		<link rel="modulepreload" href="https://_app/immutable/entry/start.PkAQ5dFz.js">
		<link rel="modulepreload" href="https://_app/immutable/chunks/entry.wLcqREKA.js">
		...

So setting the public path when you're using subdomains should be avoided. This tripped me up for several hours today, as I would expect a public path of "/" to mean the root path of the same origin.