React UI that authenticates with Okta and talks over a websocket to a Java backend

In Caddy v2, path matching is exact-match. That means that / will only match requests to /, and /ui will only match requests to /ui. You need to append a * to tell Caddy to match any path with that prefix.

E.g.

redir /ui /ui/
handle /ui/* {
    root * /app/build
    file_server
}

So my caddyfile should become:

domain

redir /ui /ui/
handle /ui/* {
    root * /app/build
    file_server
}

log {
  level DEBUG
}

?

Yeah that’s a valid Caddyfile, but I don’t know if it’ll work for your usecase :smile:

:sweat_smile: sorry, i know ive been at this for days

This does not work. caddyfile is:

domain

redir /ui /ui/
handle /ui/* {
    root * /app/build
    file_server
}

log {
  level DEBUG
}

If i take out the handle at /ui/*, then it serves a react application. The build is loaded into /app/build in a docker container, and that is I’m assuming the function of root * app/build, and the file_server will read in there. Something about changing the route on the subdomain/ to subdomain/ui, makes it unable to find the build folder

sorry more accurate to say: I believe the function of root* app/build, is to tell the file server to look in the docker container to find the build to serve

Okay, try this:

domain

root * /app/build

try_files {path} /index.html

file_server

log

I will give this a shot, but are you suggesting to put that inside the handle /ui/*? or just restart the caddyfile. if so, how does it get to the ui route?

I don’t think the handle is necessary here if the React build is right in /app/build. Is the app using a frontend router? If that’s the case, then what you typically want is for any path that doesn’t map to a file on disk to actually serve index.html instead such that it always loads the react app for any path that isn’t a static asset like your app.js or app.css, etc.

But I’m just making assumptions here, I have no idea what the application looks like. What’s actually in /app/build? (Can you run the tree command to show the file structure?) Is there any service running that you’d need to proxy to? If you can describe the setup of what you’re trying to serve with as much detail as possible, it’ll be easier to suggest what to try next.

Sure. it is a react application, that runs with react router. It does almost nothing on its own, just connects to a backend java application (thats part 2 :slight_smile: ). /app/build contains a production build, which is build from the following dockerfile:

FROM node:alpine as build
WORKDIR /app
ENV PATH /app/node_modules/bin:$PATH
COPY ./tuui/package.json /app/package.json
RUN npm install
RUN npm install react-scripts
COPY ./tuui/app
RUN npm run build

FROM caddy:2.1.1-alpine
COPY ./Caddyfile /etc/caddy/Caddyfile
COPY --from=build /app /app

With the caddyfile containing for the ui:

handle /* {
    root * /app/build
    file_server
}

it works great. When I go to /ui (by adding that in the handle, then i have issues), then i have issues. it implies that im not able to find my build anymore I think.
Does this help at all, or did I just not provide any new valuable info?

Yes, so like I said, all you should need is this:

root * /app/build

try_files {path} /index.html

file_server

No need for handle

i want it on the /ui route, so that i can have the / route for the proxy though, as like this (copied from documentation):

handle /foo/* {
	file_server
}
handle {
	reverse_proxy 127.0.0.1:8080
}

I dont understand how your suggestion gets it on the /ui route? (unless htats what path is supposed to be?)

So for that you’ll want handle_path instead, because in Caddy, the path is kept, not stripped, by default. handle_path is the same as handle, except that it also strips the prefix from the path before doing the rest.

But you should be aware that you may need to change some configuration on your React app such that the right assets are loaded on every page (there might be a base path configuration option to ensure that /ui/ is prefixed on asset paths).

Why do I have to strip the path? why can the files just be served at /ui, as opposed to /?

Because there’s a difference between the URL path and the filesystem paths. On your filesystem, there’s no /ui directory. Caddy would be looking at /app/build/ui/index.html but that doesn’t exist. So you need to strip /ui from the path before handing it the file server so that it doesn’t look for something that won’t exist.

handle_path also did not work. i see a bunch of .js and .css files, but the page itself is blank. I will also put it in the /ui folder in the build, no problem doing that

never mind that is not so simple, will have to think about that :slight_smile:

See this quote (plus read the linked wiki).

Make sure to check what configuration options are at your disposal for the build such that the base path is added.

I would strongly recommend that you try reading more of the documentation and linked threads we give you before coming back with more questions. It’ll help you learn faster and avoid having us repeat things we’ve already wrote, saving more of our time.

This is working for me, might be what you need? I see you did it earlier, but stated it wasn’t working.

I have a Gatsby React project that I used Caddy on recently via the official image on DockerHub and a volume mount to serve it. Did a quick test to emulate the subpath you are wanting to do and got the following working:

redir /ui /ui/
handle_path /ui/* {
    root * /app/build
    file_server
}

# If you get an error, you might get a blank page in the browser, but curl will show 404, this will just help when testing in the browser.
handle_errors {
	respond {http.error.status_code}
}

Side note, with Gatsby it’s expected that the build output defaults to the domain root. To serve from a subpath requires adding config and build flag to use a path prefix while building such as /ui. On disk no such directory needs to exist and handle_path as explained will drop that expectation. Otherwise it’s router logic is resetting the location bar to seem like it’s loading from the root domain (or appear like it redirected).

This topic was automatically closed after 30 days. New replies are no longer allowed.