Skip to content

Commit

Permalink
Handle rewrites for multiple HTML files
Browse files Browse the repository at this point in the history
  • Loading branch information
jgoz committed Nov 25, 2023
1 parent a84a597 commit 316a835
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/early-numbers-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'esbd': minor
---

Rewrite to appropriate HTML file based on longest matching pathname prefix
58 changes: 44 additions & 14 deletions packages/esbd/src/esbd-serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import type {
notify as notifyFn,
} from '@jgoz/esbuild-plugin-livereload';
import type { TypecheckRunner as TypecheckRunnerCls } from '@jgoz/esbuild-plugin-typecheck';
import dns from 'dns';
import fs from 'fs';
import type { ServerResponse } from 'http';
import { createServer } from 'http';
import Graceful from 'node-graceful';
import path from 'path';
import dns from 'node:dns';
import fs from 'node:fs';
import type { ServerResponse } from 'node:http';
import { createServer } from 'node:http';
import path from 'node:path';
import { URL } from 'node:url';
import { promisify } from 'node:util';
import pc from 'picocolors';
import serveStatic from 'serve-static';
import { URL } from 'url';
import { promisify } from 'util';

import type { BuildMode, ResolvedEsbdConfig, TsBuildMode } from './config';
import { getHtmlBuildOptions } from './get-build-options';
Expand Down Expand Up @@ -198,20 +198,50 @@ export default async function esbdServe(
async function handleRequest() {
await context.wait();

let normalizedUrl = url;
if (publicPath) {
// Strip "publicPath" from the beginning of the URL because
// serve-static doesn't support path remapping
req.url = new URL(
url.pathname.replace(new RegExp(`^${publicPath}`), ''),
rootUrl,
).toString();
normalizedUrl = new URL(url.pathname.replace(new RegExp(`^${publicPath}`), ''), rootUrl);
req.url = normalizedUrl.toString();
}

staticHandler(req, res, () => {
// If requested, rewrite not-found requests to the best index file based on the longest
// matching patch segment between the request URL and the template output file (SPA mode)
if (rewrite) {
// rewrite not-found requests to the index file if requested (SPA mode)
// TODO: how do we handle multiple HTML files here?
fs.createReadStream(path.resolve(absOutDir, allWriteOptions[0].template.outputPath)).pipe(
let templateOutputPath: string | undefined;
if (allWriteOptions.length === 1) {
templateOutputPath = allWriteOptions[0].template.outputPath;
} else {
const pathParts = normalizedUrl.pathname.replace(/^\//, '').split('/');
let templateSegmentMatchLength: Record<string, number> = {};

Check failure on line 218 in packages/esbd/src/esbd-serve.ts

View workflow job for this annotation

GitHub Actions / Build & Test (Node v16)

'templateSegmentMatchLength' is never reassigned. Use 'const' instead

Check failure on line 218 in packages/esbd/src/esbd-serve.ts

View workflow job for this annotation

GitHub Actions / Build & Test (Node v18)

'templateSegmentMatchLength' is never reassigned. Use 'const' instead

Check failure on line 218 in packages/esbd/src/esbd-serve.ts

View workflow job for this annotation

GitHub Actions / Build & Test (Node v20)

'templateSegmentMatchLength' is never reassigned. Use 'const' instead

for (const { template } of allWriteOptions) {
const templatePathParts = template.outputPath.replace(/^[\\/]/, '').split(path.sep);
for (let i = 0; i < templatePathParts.length; i++) {
if (templatePathParts[i] === pathParts[i]) {
templateSegmentMatchLength[template.outputPath] = i;
} else {
break;
}
}
}

const bestMatch = Object.entries(templateSegmentMatchLength).sort(
([, a], [, b]) => b - a,
)[0];

if (bestMatch) {
logger.debug(`Best match for ${url.pathname}: ${bestMatch[0]}`);
}

templateOutputPath = bestMatch?.[0] ?? allWriteOptions[0].template.outputPath;
}

logger.debug(`Rewriting ${url.pathname} to ${templateOutputPath}`);

fs.createReadStream(path.resolve(absOutDir, templateOutputPath)).pipe(
res.setHeader('Content-Type', 'text/html'),
);
return;
Expand Down

0 comments on commit 316a835

Please sign in to comment.