Skip to content

Commit 11f1509

Browse files
committed
hub/express: further tweaks/fixes for express 5.1
1 parent 480cb19 commit 11f1509

File tree

4 files changed

+20
-13
lines changed

4 files changed

+20
-13
lines changed

src/packages/hub/proxy/handle-upgrade.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
import { createProxyServer, type ProxyServer } from "http-proxy-3";
44
import LRU from "lru-cache";
5-
import { getEventListeners } from "node:events";
5+
6+
import basePath from "@cocalc/backend/base-path";
67
import getLogger from "@cocalc/hub/logger";
8+
import { getEventListeners } from "node:events";
9+
import { proxyConatWebsocket } from "./proxy-conat";
710
import stripRememberMeCookie from "./strip-remember-me-cookie";
811
import { getTarget } from "./target";
912
import { stripBasePath } from "./util";
1013
import { versionCheckFails } from "./version";
11-
import { proxyConatWebsocket } from "./proxy-conat";
12-
import basePath from "@cocalc/backend/base-path";
1314

1415
const LISTENERS_HACK = true;
1516

src/packages/hub/proxy/index.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,34 @@ interface Options {
2121
proxyConat: boolean;
2222
}
2323

24-
const uuidRegex =
24+
// UUID regex pattern for project ID validation
25+
const UUID_REGEX =
2526
/^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/;
2627

28+
/**
29+
* Middleware to validate that the project_id route parameter is a valid UUID.
30+
* If valid, continues to next middleware. If invalid, skips to next route.
31+
*/
2732
function uuidMiddleware(req, _res, next) {
28-
if (uuidRegex.test(req.params.project_id)) {
33+
if (UUID_REGEX.test(req.params.project_id)) {
2934
return next();
3035
}
31-
// Not a valid project ID UUID: skip to next matching route
36+
// Not a valid project ID UUID: skip to next route
3237
return next("route");
3338
}
3439

3540
export default function initProxy(opts: Options) {
3641
const prefix = base_path.length <= 1 ? "" : base_path;
37-
const routePath = `${prefix}/:project_id/*splat`;
38-
logger.info("creating proxy server for UUIDs only", routePath);
42+
const routePath = `${prefix}/:project_id/{*splat}`;
43+
logger.info("creating proxy server with route pattern", routePath);
3944

4045
const handleProxy = initRequest(opts);
4146

42-
const proxy_regexp = `^${prefix}\/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$\/(.*)$`;
47+
// Create regex for upgrade handler (still needed for WebSocket matching)
48+
const proxy_regexp = `^${prefix}\/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\/.*`;
4349
const handleUpgrade = initUpgrade(opts, proxy_regexp);
4450

45-
// Only handles proxy if the project_id is a valid UUID:
51+
// Use Express 5 path syntax with UUID validation middleware
4652
opts.app.all(routePath, uuidMiddleware, handleProxy);
4753

4854
opts.httpServer.on("upgrade", handleUpgrade);

src/packages/hub/servers/app/blobs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { getLogger } from "@cocalc/hub/logger";
88
const logger = getLogger("hub:servers:app:blobs");
99
export default function init(router: Router) {
1010
// return uuid-indexed blobs (mainly used for graphics)
11-
router.get("/blobs/*splat", async (req, res) => {
11+
router.get("/blobs/{*splat}", async (req, res) => {
1212
logger.debug(`${JSON.stringify(req.query)}, ${req.path}`);
1313
const uuid = `${req.query.uuid}`;
1414
if (req.headers["if-none-match"] === uuid) {

src/packages/hub/servers/app/next.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export default async function init(app: Application) {
5555
// 1: The raw static server:
5656
const raw = join(shareBasePath, "raw");
5757
app.all(
58-
join(raw, "*splat"),
58+
join(raw, "{*splat}"),
5959
(req: Request, res: Response, next: NextFunction) => {
6060
// Embedding only enabled for PDF files -- see note above
6161
const download =
@@ -77,7 +77,7 @@ export default async function init(app: Application) {
7777
// 2: The download server -- just like raw, but files always get sent via download.
7878
const download = join(shareBasePath, "download");
7979
app.all(
80-
join(download, "*splat"),
80+
join(download, "{*splat}"),
8181
(req: Request, res: Response, next: NextFunction) => {
8282
try {
8383
handleRaw({

0 commit comments

Comments
 (0)