Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 38 additions & 23 deletions packages/docusaurus/src/commands/serve/requestHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,23 @@ export function createServeRequestHandler({
'baseUrl' | 'trailingSlash'
>): ServeRequestHandler {
return async (req, res) => {
// Automatically redirect requests to /baseUrl/
if (!req.url?.startsWith(baseUrl)) {
redirect(res, baseUrl);
const redirectLocation = getRedirectLocation(req.url, {
baseUrl,
trailingSlash,
});
if (redirectLocation !== undefined) {
redirect(res, redirectLocation);
return;
}

// We do the redirect ourselves for a good reason
// server-handler is annoying and won't include /baseUrl/ in redirects
// See https://github.com/meta/docusaurus/issues/10078#issuecomment-2084932934
if (baseUrl !== '/') {
// Not super robust, but should be good enough for our use case
// See https://github.com/meta/docusaurus/pull/10090
const looksLikeAsset = !!req.url.match(/\.[a-z\d]{1,4}$/i);
if (!looksLikeAsset) {
const normalizedUrl = applyTrailingSlash(req.url, {
trailingSlash,
baseUrl,
});
if (req.url !== normalizedUrl) {
redirect(res, normalizedUrl);
return;
}
}
}

// Remove baseUrl before calling serveHandler, because /baseUrl/ should
// serve /build/index.html, not /build/baseUrl/index.html (does not exist)
// Note server-handler is really annoying here:
// - no easy way to do rewrites such as "/baseUrl/:path" => "/:path"
// - no easy way to "reapply" the baseUrl to the redirect "Location" header
// See also https://github.com/meta/docusaurus/pull/10090
req.url = req.url.replace(baseUrl, '/');
// Requests without url were redirected to the baseUrl
req.url = req.url!.replace(baseUrl, '/');

await serveHandler(req, res, {
cleanUrls: true,
Expand All @@ -66,6 +51,36 @@ export function createServeRequestHandler({
};
}

function getRedirectLocation(
url: string | undefined,
{baseUrl, trailingSlash}: Pick<DocusaurusConfig, 'baseUrl' | 'trailingSlash'>,
): string | undefined {
// Automatically redirect requests to /baseUrl/
if (!url?.startsWith(baseUrl)) {
return baseUrl;
}

// We do the redirect ourselves for a good reason
// server-handler is annoying and won't include /baseUrl/ in redirects
// See https://github.com/meta/docusaurus/issues/10078#issuecomment-2084932934
if (baseUrl !== '/') {
// Not super robust, but should be good enough for our use case
// See https://github.com/meta/docusaurus/pull/10090
const looksLikeAsset = !!url.match(/\.[a-z\d]{1,4}$/i);
if (!looksLikeAsset) {
const normalizedUrl = applyTrailingSlash(url, {
trailingSlash,
baseUrl,
});
if (url !== normalizedUrl) {
return normalizedUrl;
}
}
}

return undefined;
}

function redirect(res: http.ServerResponse, location: string) {
res.writeHead(302, {
Location: location,
Expand Down
Loading