Description
Describe the bug
I need to integrate a SvelteKit app into an existing Express.js server at a dynamic base path. Based on #595 (comment) I assume this is intended to be supported through the kit.paths.relative
option, but there's a bit of a snafu with trailing slashes on the base path.
Standard static paths.base
behavior (repro branch)
With a configuration like this:
const config = {
kit: {
adapter: adapterNode(),
paths: {
base: '/sveltekit',
relative: true
}
}
}
...and integration into a custom server like this:
app.use(handler);
/sveltekit
is always redirected to /sveltekit/
, regardless of trailingSlash
configuration. This makes sense, because the trailing slash is necessary to resolve relative paths starting with ./
correctly.
This seems to be handled by this snippet that eventually ends up in build/server/index.js
:
kit/packages/kit/src/runtime/server/respond.js
Lines 298 to 301 in 0b60ea7
Dynamic paths.base
attempt (repro branch)
With a configuration like this:
const config = {
kit: {
adapter: adapterNode(),
paths: {
relative: true
}
}
};
...and integration like this:
app.use('/sveltekit', handler);
/sveltekit
is no longer redirected to /sveltekit/
, regardless of trailingSlash
configuration. As expected this breaks basically everything with a relative path.
Reproduction
HoldYourWaffle/sveltekit-express-dynamic-basepath, specifically repro--static-base
and repro--dynamic-base
.
System Info
System:
OS: Windows 10 10.0.19045
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 16.98 GB / 31.81 GB
Binaries:
Node: 22.14.0 - C:\Program Files\nodejs\node.EXE
npm: 10.9.2 - C:\Program Files\nodejs\npm.CMD
pnpm: 10.6.2 - ~\AppData\Local\pnpm\pnpm.CMD
Browsers:
Edge: Chromium (133.0.3065.69)
Internet Explorer: 11.0.19041.4355
Severity
serious, but I can work around it
Additional Information
After some digging I realized that app.use
strips out the provided prefix path, which causes url.pathname
to be /
in both situations, therefore the aforementioned check can't tell the difference.
I assume #7242 would solve this issue, since there's no need to pass a prefix path to app.use
if paths.base
can be provided at runtime.
Workaround
In my case I can just implement the redirect myself outside the context of app.use
:
app.all('/sveltekit', (req, res, next) => {
if (!req.url.endsWith('/')) {
res.redirect(308, '/sveltekit/');
} else {
next();
}
});
app.use('/sveltekit', handler);