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.
- 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.
- 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:
- Host Temporal Frontend service (I've got it on ECS) with
TEMPORAL_UI_PUBLIC_PATH=/
- 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 = [
"/*",
]
}
}
- 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.