heliumts 0.7.6 → 0.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,7 +42,7 @@ export function attachToDevServer(httpServer, loadHandlers, config = {}, workers
42
42
  // Re-initialize rate limiter with new config (always recreate in dev mode to pick up config changes)
43
43
  rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);
44
44
  const registry = new RpcRegistry();
45
- const httpRouter = new HTTPRouter();
45
+ const httpRouter = new HTTPRouter({ maxBodySize: rpcConfig.maxBodySize });
46
46
  const seoRouter = new SEOMetadataRouter();
47
47
  httpRouter.setTrustProxyDepth(trustProxyDepth);
48
48
  loadHandlers(registry, httpRouter, seoRouter);
@@ -1 +1 @@
1
- {"version":3,"file":"devServer.js","sourceRoot":"","sources":["../../src/server/devServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode as msgpackEncode } from \"@msgpack/msgpack\";\nimport type http from \"http\";\nimport type http2 from \"http2\";\nimport type https from \"https\";\nimport { promisify } from \"util\";\nimport type WebSocket from \"ws\";\nimport { WebSocketServer } from \"ws\";\nimport { brotliCompress, deflate, gzip } from \"zlib\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { injectEnvToProcess, loadEnvFiles } from \"../utils/envLoader.js\";\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumConfig } from \"./config.js\";\nimport { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from \"./config.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumWorkerDef } from \"./defineWorker.js\";\nimport { startWorker, stopAllWorkers } from \"./defineWorker.js\";\nimport { HTTPRouter } from \"./httpRouter.js\";\nimport { injectSocialMetaIntoHtml, loadDefaultSocialMetaFromHtmlFile } from \"./meta.js\";\nimport { RateLimiter } from \"./rateLimiter.js\";\nimport { RpcRegistry } from \"./rpcRegistry.js\";\nimport { initializeSecurity, verifyConnectionToken } from \"./security.js\";\nimport { SEOMetadataRouter } from \"./seoMetadataRouter.js\";\nimport { prepareForMsgpack } from \"./serializer.js\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\nconst brotliCompressAsync = promisify(brotliCompress);\n\ntype LoadHandlersFn = (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;\ntype HttpServer = http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer;\n\ninterface WorkerEntry {\n name: string;\n worker: HeliumWorkerDef;\n}\n\nlet currentRegistry: RpcRegistry | null = null;\nlet currentHttpRouter: HTTPRouter | null = null;\nlet currentSEORouter: SEOMetadataRouter | null = null;\nlet wss: WebSocketServer | null = null;\nlet rateLimiter: RateLimiter | null = null;\nlet currentWorkers: WorkerEntry[] = [];\nlet cachedDefaultMeta: Awaited<ReturnType<typeof loadDefaultSocialMetaFromHtmlFile>> | undefined;\n\n/**\n * Attaches HeliumTS HTTP handlers and WebSocket RPC server to an existing HTTP server.\n * This is used in dev mode to attach to Vite's dev server.\n */\nexport function attachToDevServer(httpServer: HttpServer, loadHandlers: LoadHandlersFn, config: HeliumConfig = {}, workers: WorkerEntry[] = []) {\n // Load environment variables for server-side access\n const envVars = loadEnvFiles();\n injectEnvToProcess(envVars);\n\n // Load configuration\n const trustProxyDepth = getTrustProxyDepth(config);\n const rpcSecurity = getRpcSecurityConfig(config);\n const rpcConfig = getRpcConfig(config);\n const compressionConfig = rpcConfig.compression;\n initializeSecurity(rpcSecurity);\n\n // Re-initialize rate limiter with new config (always recreate in dev mode to pick up config changes)\n rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);\n\n const registry = new RpcRegistry();\n const httpRouter = new HTTPRouter();\n const seoRouter = new SEOMetadataRouter();\n httpRouter.setTrustProxyDepth(trustProxyDepth);\n loadHandlers(registry, httpRouter, seoRouter);\n registry.setRateLimiter(rateLimiter);\n registry.setMaxBatchSize(rpcConfig.maxBatchSize);\n currentRegistry = registry;\n currentHttpRouter = httpRouter;\n currentSEORouter = seoRouter;\n cachedDefaultMeta = undefined;\n\n const getDefaultMeta = async () => {\n if (cachedDefaultMeta !== undefined) {\n return cachedDefaultMeta;\n }\n\n cachedDefaultMeta = await loadDefaultSocialMetaFromHtmlFile(`${process.cwd()}/index.html`);\n return cachedDefaultMeta;\n };\n\n registry.register(SEO_METADATA_RPC_METHOD, {\n __kind: \"method\",\n __id: SEO_METADATA_RPC_METHOD,\n handler: async (args: { path?: string } | undefined, ctx: HeliumContext) => {\n const requestedPath = typeof args?.path === \"string\" ? args.path : \"/\";\n const targetPath = requestedPath.startsWith(\"/\") ? requestedPath : `/${requestedPath}`;\n const metadata = await seoRouter.resolve(ctx.req.raw, ctx, targetPath);\n return metadata ?? (await getDefaultMeta());\n },\n });\n currentSEORouter = seoRouter;\n\n // Start workers if they changed\n const workersChanged = workers.length !== currentWorkers.length || workers.some((w, i) => w.name !== currentWorkers[i]?.name || w.worker !== currentWorkers[i]?.worker);\n\n if (workersChanged && workers.length > 0) {\n // Stop all existing workers before starting new ones\n stopAllWorkers().then(() => {\n // Start new workers\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n currentWorkers = workers;\n });\n } else if (currentWorkers.length === 0 && workers.length > 0) {\n // First time starting workers\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n currentWorkers = workers;\n }\n\n // Attach WebSocket server if not already attached\n if (!wss) {\n wss = new WebSocketServer({\n noServer: true,\n maxPayload: rpcConfig.maxWsPayload,\n perMessageDeflate: compressionConfig.enabled\n ? {\n zlibDeflateOptions: {\n chunkSize: 1024,\n memLevel: 7,\n level: 9, // 6 is default compression level (balanced)\n },\n zlibInflateOptions: {\n chunkSize: 10 * 1024,\n },\n threshold: compressionConfig.threshold,\n }\n : false,\n });\n\n wss.on(\"connection\", (socket: WebSocket, req: http.IncomingMessage) => {\n // Extract client IP with proxy configuration\n const ip = extractClientIP(req, trustProxyDepth);\n\n // Store connection metadata for RPC context\n if (currentRegistry) {\n currentRegistry.setSocketMetadata(socket, ip, req);\n }\n\n // Track connection and check IP limit\n if (rateLimiter && !rateLimiter.trackConnection(socket, ip)) {\n socket.close(1008, \"Too many connections from your IP\");\n return;\n }\n\n // Prevent unhandled errors from crashing the process (e.g. maxPayload exceeded)\n socket.on(\"error\", (err) => {\n log(\"warn\", \"WebSocket error:\", err);\n if (socket.readyState === socket.OPEN || socket.readyState === socket.CLOSING) {\n socket.close(1009, \"Message too large\");\n }\n });\n\n socket.on(\"message\", (msg: WebSocket.RawData, _isBinary: boolean) => {\n // Check rate limit\n if (rateLimiter && !rateLimiter.checkRateLimit(socket)) {\n // Parse request to get the ID for proper error response\n try {\n let req: any;\n // Always expect MessagePack\n const buffer = Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any);\n const { decode: msgpackDecode } = require(\"@msgpack/msgpack\");\n req = msgpackDecode(buffer);\n\n const stats = rateLimiter.getConnectionStats(socket);\n const now = Date.now();\n const resetInSeconds = stats ? Math.ceil((stats.resetTimeMs - now) / 1000) : 0;\n\n const createError = (id: string) => ({\n id,\n ok: false,\n stats: {\n remainingRequests: stats ? stats.remainingMessages : 0,\n resetInSeconds,\n },\n error: \"Rate limit exceeded\",\n });\n\n let errorResponse: any;\n if (Array.isArray(req)) {\n errorResponse = req.map((r: any) => createError(r.id));\n } else {\n errorResponse = createError(req.id);\n }\n\n socket.send(msgpackEncode(errorResponse) as Buffer);\n } catch {\n // If we can't parse the request, just close the connection\n socket.close();\n }\n return;\n }\n\n // Always use the current registry (may have been updated)\n if (currentRegistry) {\n currentRegistry.handleMessage(socket, Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any));\n }\n });\n });\n\n // Handle WebSocket upgrade requests\n httpServer.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/rpc\")) {\n // Security: read token from Sec-WebSocket-Protocol header instead of query string\n const protocols = req.headers[\"sec-websocket-protocol\"];\n const token =\n typeof protocols === \"string\"\n ? protocols\n .split(\",\")\n .map((p) => p.trim())\n .find((p) => p.includes(\".\"))\n : undefined;\n\n if (!token || !verifyConnectionToken(token)) {\n log(\"warn\", \"WebSocket connection rejected - invalid token\");\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n // Check IP connection limit before upgrading\n const ip = extractClientIP(req, trustProxyDepth);\n if (rateLimiter && rpcSecurity.maxConnectionsPerIP > 0) {\n const currentConnections = rateLimiter.getIPConnectionCount(ip);\n if (currentConnections >= rpcSecurity.maxConnectionsPerIP) {\n log(\"warn\", `WebSocket connection rejected - IP ${ip} has ${currentConnections} connections`);\n socket.write(\"HTTP/1.1 429 Too Many Requests\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss!.handleUpgrade(req, socket, head, (ws) => {\n wss!.emit(\"connection\", ws, req);\n });\n }\n });\n\n log(\"info\", \"WebSocket RPC attached to dev server at /rpc\");\n }\n\n // Security: max body size for HTTP requests\n const maxBodySize = rpcConfig.maxBodySize ?? 1_048_576;\n\n // Attach HTTP request handler\n // We need to intercept requests before Vite handles them\n const originalListeners = httpServer.listeners(\"request\").slice();\n httpServer.removeAllListeners(\"request\");\n\n httpServer.on(\"request\", async (req: any, res: any) => {\n // Handle token refresh endpoint\n if (req.url === \"/__helium__/refresh-token\") {\n // Security: only allow POST to prevent CSRF via <img>/<script> tags\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n // Security: require custom header to prevent cross-origin requests\n if (!req.headers[\"x-requested-with\"]) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Forbidden\" }));\n return;\n }\n const { generateConnectionToken } = await import(\"./security.js\");\n const token = generateConnectionToken();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ token }));\n return;\n }\n\n // Handle HTTP-based RPC endpoint (alternative to WebSocket for mobile networks)\n if (req.url === \"/__helium__/rpc\" && req.method === \"POST\") {\n // Security: verify connection token for HTTP RPC\n const authToken = req.headers[\"x-helium-token\"] as string | undefined;\n if (!authToken || !verifyConnectionToken(authToken)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Unauthorized\" }));\n return;\n }\n\n // Security: check Content-Length before reading body\n const contentLength = parseInt(req.headers[\"content-length\"] || \"0\", 10);\n if (contentLength > maxBodySize) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n let aborted = false;\n req.on(\"data\", (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > maxBodySize) {\n aborted = true;\n req.destroy();\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", async () => {\n if (aborted) {\n return;\n }\n try {\n if (!currentRegistry) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Server not ready\" }));\n return;\n }\n\n const body = Buffer.concat(chunks);\n const ip = extractClientIP(req, trustProxyDepth);\n const result = await currentRegistry.handleHttpRequest(body, ip, req);\n\n const encoded = msgpackEncode(prepareForMsgpack(result.response));\n let responseBody = Buffer.from(encoded as Uint8Array);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/msgpack\",\n \"Cache-Control\": \"no-store\",\n };\n\n // Handle compression\n const acceptEncoding = req.headers[\"accept-encoding\"] as string;\n if (acceptEncoding && responseBody.length > 1024) {\n if (acceptEncoding.includes(\"br\")) {\n responseBody = await brotliCompressAsync(responseBody);\n headers[\"Content-Encoding\"] = \"br\";\n } else if (acceptEncoding.includes(\"gzip\")) {\n responseBody = await gzipAsync(responseBody);\n headers[\"Content-Encoding\"] = \"gzip\";\n } else if (acceptEncoding.includes(\"deflate\")) {\n responseBody = await deflateAsync(responseBody);\n headers[\"Content-Encoding\"] = \"deflate\";\n }\n }\n\n res.writeHead(200, headers);\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"HTTP RPC error:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Internal server error\" }));\n }\n });\n return;\n }\n\n // Try HTTP handlers first\n if (currentHttpRouter) {\n const handled = await currentHttpRouter.handleRequest(req, res);\n if (handled) {\n return;\n }\n }\n\n let devResolvedMetadata: Awaited<ReturnType<SEOMetadataRouter[\"resolve\"]>> = null;\n if (currentSEORouter) {\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n devResolvedMetadata = await currentSEORouter.resolve(req, httpCtx);\n }\n\n if (devResolvedMetadata) {\n const originalWriteHead = res.writeHead.bind(res);\n const originalWrite = res.write.bind(res);\n const originalEnd = res.end.bind(res);\n const bufferedChunks: Buffer[] = [];\n let capturedContentType = \"\";\n\n res.writeHead = (statusCode: number, statusMessageOrHeaders?: any, headers?: any) => {\n const providedHeaders = typeof statusMessageOrHeaders === \"string\" ? headers : statusMessageOrHeaders;\n\n if (providedHeaders) {\n if (Array.isArray(providedHeaders)) {\n for (let i = 0; i < providedHeaders.length; i += 2) {\n if (String(providedHeaders[i]).toLowerCase() === \"content-type\") {\n capturedContentType = String(providedHeaders[i + 1] || \"\").toLowerCase();\n break;\n }\n }\n } else if (typeof providedHeaders === \"object\") {\n const maybeContentType = providedHeaders[\"Content-Type\"] ?? providedHeaders[\"content-type\"];\n if (maybeContentType) {\n capturedContentType = String(maybeContentType).toLowerCase();\n }\n }\n }\n\n return originalWriteHead(statusCode, statusMessageOrHeaders, headers);\n };\n\n res.write = (chunk: any, encoding?: BufferEncoding | (() => void), callback?: () => void) => {\n if (chunk !== undefined && chunk !== null) {\n bufferedChunks.push(toBuffer(chunk, typeof encoding === \"string\" ? encoding : undefined));\n }\n\n if (typeof encoding === \"function\") {\n encoding();\n } else if (typeof callback === \"function\") {\n callback();\n }\n\n return true;\n };\n\n res.end = (chunk?: any, encoding?: BufferEncoding | (() => void), callback?: () => void) => {\n if (chunk !== undefined && chunk !== null) {\n bufferedChunks.push(toBuffer(chunk, typeof encoding === \"string\" ? encoding : undefined));\n }\n\n if (typeof encoding === \"function\") {\n encoding();\n } else if (typeof callback === \"function\") {\n callback();\n }\n\n const bodyBuffer = Buffer.concat(bufferedChunks);\n const bodyText = bodyBuffer.toString(\"utf-8\");\n const contentType = capturedContentType || String(res.getHeader(\"content-type\") || \"\").toLowerCase();\n const looksLikeHtml = /^\\s*<!doctype\\s+html|^\\s*<html[\\s>]/i.test(bodyText);\n\n res.writeHead = originalWriteHead;\n res.write = originalWrite;\n res.end = originalEnd;\n\n if (contentType.includes(\"text/html\") || looksLikeHtml) {\n const injectedHtml = injectSocialMetaIntoHtml(bodyText, devResolvedMetadata);\n return originalEnd(Buffer.from(injectedHtml, \"utf-8\"));\n }\n\n return originalEnd(bodyBuffer);\n };\n }\n\n // If no handler matched, pass to original Vite handlers\n for (const listener of originalListeners) {\n (listener as any)(req, res);\n }\n });\n}\n\nfunction toBuffer(chunk: unknown, encoding?: BufferEncoding): Buffer {\n if (Buffer.isBuffer(chunk)) {\n return chunk;\n }\n\n if (chunk instanceof Uint8Array) {\n return Buffer.from(chunk);\n }\n\n if (typeof chunk === \"string\") {\n return Buffer.from(chunk, encoding);\n }\n\n return Buffer.from(String(chunk), encoding);\n}\n"]}
1
+ {"version":3,"file":"devServer.js","sourceRoot":"","sources":["../../src/server/devServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode as msgpackEncode } from \"@msgpack/msgpack\";\nimport type http from \"http\";\nimport type http2 from \"http2\";\nimport type https from \"https\";\nimport { promisify } from \"util\";\nimport type WebSocket from \"ws\";\nimport { WebSocketServer } from \"ws\";\nimport { brotliCompress, deflate, gzip } from \"zlib\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { injectEnvToProcess, loadEnvFiles } from \"../utils/envLoader.js\";\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumConfig } from \"./config.js\";\nimport { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from \"./config.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumWorkerDef } from \"./defineWorker.js\";\nimport { startWorker, stopAllWorkers } from \"./defineWorker.js\";\nimport { HTTPRouter } from \"./httpRouter.js\";\nimport { injectSocialMetaIntoHtml, loadDefaultSocialMetaFromHtmlFile } from \"./meta.js\";\nimport { RateLimiter } from \"./rateLimiter.js\";\nimport { RpcRegistry } from \"./rpcRegistry.js\";\nimport { initializeSecurity, verifyConnectionToken } from \"./security.js\";\nimport { SEOMetadataRouter } from \"./seoMetadataRouter.js\";\nimport { prepareForMsgpack } from \"./serializer.js\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\nconst brotliCompressAsync = promisify(brotliCompress);\n\ntype LoadHandlersFn = (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;\ntype HttpServer = http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer;\n\ninterface WorkerEntry {\n name: string;\n worker: HeliumWorkerDef;\n}\n\nlet currentRegistry: RpcRegistry | null = null;\nlet currentHttpRouter: HTTPRouter | null = null;\nlet currentSEORouter: SEOMetadataRouter | null = null;\nlet wss: WebSocketServer | null = null;\nlet rateLimiter: RateLimiter | null = null;\nlet currentWorkers: WorkerEntry[] = [];\nlet cachedDefaultMeta: Awaited<ReturnType<typeof loadDefaultSocialMetaFromHtmlFile>> | undefined;\n\n/**\n * Attaches HeliumTS HTTP handlers and WebSocket RPC server to an existing HTTP server.\n * This is used in dev mode to attach to Vite's dev server.\n */\nexport function attachToDevServer(httpServer: HttpServer, loadHandlers: LoadHandlersFn, config: HeliumConfig = {}, workers: WorkerEntry[] = []) {\n // Load environment variables for server-side access\n const envVars = loadEnvFiles();\n injectEnvToProcess(envVars);\n\n // Load configuration\n const trustProxyDepth = getTrustProxyDepth(config);\n const rpcSecurity = getRpcSecurityConfig(config);\n const rpcConfig = getRpcConfig(config);\n const compressionConfig = rpcConfig.compression;\n initializeSecurity(rpcSecurity);\n\n // Re-initialize rate limiter with new config (always recreate in dev mode to pick up config changes)\n rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);\n\n const registry = new RpcRegistry();\n const httpRouter = new HTTPRouter({ maxBodySize: rpcConfig.maxBodySize });\n const seoRouter = new SEOMetadataRouter();\n httpRouter.setTrustProxyDepth(trustProxyDepth);\n loadHandlers(registry, httpRouter, seoRouter);\n registry.setRateLimiter(rateLimiter);\n registry.setMaxBatchSize(rpcConfig.maxBatchSize);\n currentRegistry = registry;\n currentHttpRouter = httpRouter;\n currentSEORouter = seoRouter;\n cachedDefaultMeta = undefined;\n\n const getDefaultMeta = async () => {\n if (cachedDefaultMeta !== undefined) {\n return cachedDefaultMeta;\n }\n\n cachedDefaultMeta = await loadDefaultSocialMetaFromHtmlFile(`${process.cwd()}/index.html`);\n return cachedDefaultMeta;\n };\n\n registry.register(SEO_METADATA_RPC_METHOD, {\n __kind: \"method\",\n __id: SEO_METADATA_RPC_METHOD,\n handler: async (args: { path?: string } | undefined, ctx: HeliumContext) => {\n const requestedPath = typeof args?.path === \"string\" ? args.path : \"/\";\n const targetPath = requestedPath.startsWith(\"/\") ? requestedPath : `/${requestedPath}`;\n const metadata = await seoRouter.resolve(ctx.req.raw, ctx, targetPath);\n return metadata ?? (await getDefaultMeta());\n },\n });\n currentSEORouter = seoRouter;\n\n // Start workers if they changed\n const workersChanged = workers.length !== currentWorkers.length || workers.some((w, i) => w.name !== currentWorkers[i]?.name || w.worker !== currentWorkers[i]?.worker);\n\n if (workersChanged && workers.length > 0) {\n // Stop all existing workers before starting new ones\n stopAllWorkers().then(() => {\n // Start new workers\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n currentWorkers = workers;\n });\n } else if (currentWorkers.length === 0 && workers.length > 0) {\n // First time starting workers\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n currentWorkers = workers;\n }\n\n // Attach WebSocket server if not already attached\n if (!wss) {\n wss = new WebSocketServer({\n noServer: true,\n maxPayload: rpcConfig.maxWsPayload,\n perMessageDeflate: compressionConfig.enabled\n ? {\n zlibDeflateOptions: {\n chunkSize: 1024,\n memLevel: 7,\n level: 9, // 6 is default compression level (balanced)\n },\n zlibInflateOptions: {\n chunkSize: 10 * 1024,\n },\n threshold: compressionConfig.threshold,\n }\n : false,\n });\n\n wss.on(\"connection\", (socket: WebSocket, req: http.IncomingMessage) => {\n // Extract client IP with proxy configuration\n const ip = extractClientIP(req, trustProxyDepth);\n\n // Store connection metadata for RPC context\n if (currentRegistry) {\n currentRegistry.setSocketMetadata(socket, ip, req);\n }\n\n // Track connection and check IP limit\n if (rateLimiter && !rateLimiter.trackConnection(socket, ip)) {\n socket.close(1008, \"Too many connections from your IP\");\n return;\n }\n\n // Prevent unhandled errors from crashing the process (e.g. maxPayload exceeded)\n socket.on(\"error\", (err) => {\n log(\"warn\", \"WebSocket error:\", err);\n if (socket.readyState === socket.OPEN || socket.readyState === socket.CLOSING) {\n socket.close(1009, \"Message too large\");\n }\n });\n\n socket.on(\"message\", (msg: WebSocket.RawData, _isBinary: boolean) => {\n // Check rate limit\n if (rateLimiter && !rateLimiter.checkRateLimit(socket)) {\n // Parse request to get the ID for proper error response\n try {\n let req: any;\n // Always expect MessagePack\n const buffer = Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any);\n const { decode: msgpackDecode } = require(\"@msgpack/msgpack\");\n req = msgpackDecode(buffer);\n\n const stats = rateLimiter.getConnectionStats(socket);\n const now = Date.now();\n const resetInSeconds = stats ? Math.ceil((stats.resetTimeMs - now) / 1000) : 0;\n\n const createError = (id: string) => ({\n id,\n ok: false,\n stats: {\n remainingRequests: stats ? stats.remainingMessages : 0,\n resetInSeconds,\n },\n error: \"Rate limit exceeded\",\n });\n\n let errorResponse: any;\n if (Array.isArray(req)) {\n errorResponse = req.map((r: any) => createError(r.id));\n } else {\n errorResponse = createError(req.id);\n }\n\n socket.send(msgpackEncode(errorResponse) as Buffer);\n } catch {\n // If we can't parse the request, just close the connection\n socket.close();\n }\n return;\n }\n\n // Always use the current registry (may have been updated)\n if (currentRegistry) {\n currentRegistry.handleMessage(socket, Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any));\n }\n });\n });\n\n // Handle WebSocket upgrade requests\n httpServer.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/rpc\")) {\n // Security: read token from Sec-WebSocket-Protocol header instead of query string\n const protocols = req.headers[\"sec-websocket-protocol\"];\n const token =\n typeof protocols === \"string\"\n ? protocols\n .split(\",\")\n .map((p) => p.trim())\n .find((p) => p.includes(\".\"))\n : undefined;\n\n if (!token || !verifyConnectionToken(token)) {\n log(\"warn\", \"WebSocket connection rejected - invalid token\");\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n // Check IP connection limit before upgrading\n const ip = extractClientIP(req, trustProxyDepth);\n if (rateLimiter && rpcSecurity.maxConnectionsPerIP > 0) {\n const currentConnections = rateLimiter.getIPConnectionCount(ip);\n if (currentConnections >= rpcSecurity.maxConnectionsPerIP) {\n log(\"warn\", `WebSocket connection rejected - IP ${ip} has ${currentConnections} connections`);\n socket.write(\"HTTP/1.1 429 Too Many Requests\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss!.handleUpgrade(req, socket, head, (ws) => {\n wss!.emit(\"connection\", ws, req);\n });\n }\n });\n\n log(\"info\", \"WebSocket RPC attached to dev server at /rpc\");\n }\n\n // Security: max body size for HTTP requests\n const maxBodySize = rpcConfig.maxBodySize ?? 1_048_576;\n\n // Attach HTTP request handler\n // We need to intercept requests before Vite handles them\n const originalListeners = httpServer.listeners(\"request\").slice();\n httpServer.removeAllListeners(\"request\");\n\n httpServer.on(\"request\", async (req: any, res: any) => {\n // Handle token refresh endpoint\n if (req.url === \"/__helium__/refresh-token\") {\n // Security: only allow POST to prevent CSRF via <img>/<script> tags\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n // Security: require custom header to prevent cross-origin requests\n if (!req.headers[\"x-requested-with\"]) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Forbidden\" }));\n return;\n }\n const { generateConnectionToken } = await import(\"./security.js\");\n const token = generateConnectionToken();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ token }));\n return;\n }\n\n // Handle HTTP-based RPC endpoint (alternative to WebSocket for mobile networks)\n if (req.url === \"/__helium__/rpc\" && req.method === \"POST\") {\n // Security: verify connection token for HTTP RPC\n const authToken = req.headers[\"x-helium-token\"] as string | undefined;\n if (!authToken || !verifyConnectionToken(authToken)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Unauthorized\" }));\n return;\n }\n\n // Security: check Content-Length before reading body\n const contentLength = parseInt(req.headers[\"content-length\"] || \"0\", 10);\n if (contentLength > maxBodySize) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n let aborted = false;\n req.on(\"data\", (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > maxBodySize) {\n aborted = true;\n req.destroy();\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", async () => {\n if (aborted) {\n return;\n }\n try {\n if (!currentRegistry) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Server not ready\" }));\n return;\n }\n\n const body = Buffer.concat(chunks);\n const ip = extractClientIP(req, trustProxyDepth);\n const result = await currentRegistry.handleHttpRequest(body, ip, req);\n\n const encoded = msgpackEncode(prepareForMsgpack(result.response));\n let responseBody = Buffer.from(encoded as Uint8Array);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/msgpack\",\n \"Cache-Control\": \"no-store\",\n };\n\n // Handle compression\n const acceptEncoding = req.headers[\"accept-encoding\"] as string;\n if (acceptEncoding && responseBody.length > 1024) {\n if (acceptEncoding.includes(\"br\")) {\n responseBody = await brotliCompressAsync(responseBody);\n headers[\"Content-Encoding\"] = \"br\";\n } else if (acceptEncoding.includes(\"gzip\")) {\n responseBody = await gzipAsync(responseBody);\n headers[\"Content-Encoding\"] = \"gzip\";\n } else if (acceptEncoding.includes(\"deflate\")) {\n responseBody = await deflateAsync(responseBody);\n headers[\"Content-Encoding\"] = \"deflate\";\n }\n }\n\n res.writeHead(200, headers);\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"HTTP RPC error:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Internal server error\" }));\n }\n });\n return;\n }\n\n // Try HTTP handlers first\n if (currentHttpRouter) {\n const handled = await currentHttpRouter.handleRequest(req, res);\n if (handled) {\n return;\n }\n }\n\n let devResolvedMetadata: Awaited<ReturnType<SEOMetadataRouter[\"resolve\"]>> = null;\n if (currentSEORouter) {\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n devResolvedMetadata = await currentSEORouter.resolve(req, httpCtx);\n }\n\n if (devResolvedMetadata) {\n const originalWriteHead = res.writeHead.bind(res);\n const originalWrite = res.write.bind(res);\n const originalEnd = res.end.bind(res);\n const bufferedChunks: Buffer[] = [];\n let capturedContentType = \"\";\n\n res.writeHead = (statusCode: number, statusMessageOrHeaders?: any, headers?: any) => {\n const providedHeaders = typeof statusMessageOrHeaders === \"string\" ? headers : statusMessageOrHeaders;\n\n if (providedHeaders) {\n if (Array.isArray(providedHeaders)) {\n for (let i = 0; i < providedHeaders.length; i += 2) {\n if (String(providedHeaders[i]).toLowerCase() === \"content-type\") {\n capturedContentType = String(providedHeaders[i + 1] || \"\").toLowerCase();\n break;\n }\n }\n } else if (typeof providedHeaders === \"object\") {\n const maybeContentType = providedHeaders[\"Content-Type\"] ?? providedHeaders[\"content-type\"];\n if (maybeContentType) {\n capturedContentType = String(maybeContentType).toLowerCase();\n }\n }\n }\n\n return originalWriteHead(statusCode, statusMessageOrHeaders, headers);\n };\n\n res.write = (chunk: any, encoding?: BufferEncoding | (() => void), callback?: () => void) => {\n if (chunk !== undefined && chunk !== null) {\n bufferedChunks.push(toBuffer(chunk, typeof encoding === \"string\" ? encoding : undefined));\n }\n\n if (typeof encoding === \"function\") {\n encoding();\n } else if (typeof callback === \"function\") {\n callback();\n }\n\n return true;\n };\n\n res.end = (chunk?: any, encoding?: BufferEncoding | (() => void), callback?: () => void) => {\n if (chunk !== undefined && chunk !== null) {\n bufferedChunks.push(toBuffer(chunk, typeof encoding === \"string\" ? encoding : undefined));\n }\n\n if (typeof encoding === \"function\") {\n encoding();\n } else if (typeof callback === \"function\") {\n callback();\n }\n\n const bodyBuffer = Buffer.concat(bufferedChunks);\n const bodyText = bodyBuffer.toString(\"utf-8\");\n const contentType = capturedContentType || String(res.getHeader(\"content-type\") || \"\").toLowerCase();\n const looksLikeHtml = /^\\s*<!doctype\\s+html|^\\s*<html[\\s>]/i.test(bodyText);\n\n res.writeHead = originalWriteHead;\n res.write = originalWrite;\n res.end = originalEnd;\n\n if (contentType.includes(\"text/html\") || looksLikeHtml) {\n const injectedHtml = injectSocialMetaIntoHtml(bodyText, devResolvedMetadata);\n return originalEnd(Buffer.from(injectedHtml, \"utf-8\"));\n }\n\n return originalEnd(bodyBuffer);\n };\n }\n\n // If no handler matched, pass to original Vite handlers\n for (const listener of originalListeners) {\n (listener as any)(req, res);\n }\n });\n}\n\nfunction toBuffer(chunk: unknown, encoding?: BufferEncoding): Buffer {\n if (Buffer.isBuffer(chunk)) {\n return chunk;\n }\n\n if (chunk instanceof Uint8Array) {\n return Buffer.from(chunk);\n }\n\n if (typeof chunk === \"string\") {\n return Buffer.from(chunk, encoding);\n }\n\n return Buffer.from(String(chunk), encoding);\n}\n"]}
@@ -5,13 +5,19 @@ export interface HTTPRoute {
5
5
  name: string;
6
6
  handler: HeliumHTTPDef;
7
7
  }
8
+ interface HTTPRouterOptions {
9
+ maxBodySize?: number;
10
+ }
8
11
  export declare class HTTPRouter {
9
12
  private routes;
10
13
  private middleware;
11
14
  private trustProxyDepth;
15
+ private maxBodySize;
16
+ constructor(options?: HTTPRouterOptions);
12
17
  setTrustProxyDepth(depth: number): void;
13
18
  registerRoutes(routes: HTTPRoute[]): void;
14
19
  setMiddleware(middleware: HeliumMiddleware): void;
15
20
  handleRequest(req: IncomingMessage, res: ServerResponse, ctx?: unknown): Promise<boolean>;
16
21
  }
22
+ export {};
17
23
  //# sourceMappingURL=httpRouter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"httpRouter.d.ts","sourceRoot":"","sources":["../../src/server/httpRouter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAM5D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;CAC1B;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAKN;IACR,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,eAAe,CAAa;IAEpC,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAIhC,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE;IAalC,aAAa,CAAC,UAAU,EAAE,gBAAgB;IAIpC,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAsGlG"}
1
+ {"version":3,"file":"httpRouter.d.ts","sourceRoot":"","sources":["../../src/server/httpRouter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAM5D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;CAC1B;AAED,UAAU,iBAAiB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAKN;IACR,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,iBAAsB;IAI3C,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAIhC,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE;IAalC,aAAa,CAAC,UAAU,EAAE,gBAAgB;IAIpC,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAsGlG"}
@@ -2,10 +2,11 @@ import { parse as parseUrl } from "url";
2
2
  import { extractClientIP } from "../utils/ipExtractor.js";
3
3
  import { log } from "../utils/logger.js";
4
4
  export class HTTPRouter {
5
- constructor() {
5
+ constructor(options = {}) {
6
6
  this.routes = [];
7
7
  this.middleware = null;
8
8
  this.trustProxyDepth = 0;
9
+ this.maxBodySize = options.maxBodySize ?? 1048576;
9
10
  }
10
11
  setTrustProxyDepth(depth) {
11
12
  this.trustProxyDepth = depth;
@@ -51,7 +52,7 @@ export class HTTPRouter {
51
52
  }
52
53
  }
53
54
  }
54
- const httpRequest = await createHTTPRequest(req, query, params);
55
+ const httpRequest = await createHTTPRequest(req, query, params, this.maxBodySize);
55
56
  let result;
56
57
  // Build context with request metadata
57
58
  const ip = extractClientIP(req, this.trustProxyDepth);
@@ -135,7 +136,7 @@ function pathToRegex(path) {
135
136
  keys,
136
137
  };
137
138
  }
138
- async function createHTTPRequest(req, query, params) {
139
+ async function createHTTPRequest(req, query, params, maxBodySize) {
139
140
  const headers = {};
140
141
  for (const [key, value] of Object.entries(req.headers)) {
141
142
  headers[key.toLowerCase()] = value;
@@ -149,7 +150,7 @@ async function createHTTPRequest(req, query, params) {
149
150
  let bodyBuffer = null;
150
151
  const getBody = async () => {
151
152
  if (bodyBuffer === null) {
152
- bodyBuffer = await readBody(req);
153
+ bodyBuffer = await readBody(req, maxBodySize);
153
154
  }
154
155
  return bodyBuffer;
155
156
  };
@@ -201,10 +202,11 @@ async function createHTTPRequest(req, query, params) {
201
202
  }
202
203
  }
203
204
  const body = req.method !== "GET" && req.method !== "HEAD" ? await getBody() : undefined;
205
+ const requestBody = body ? Uint8Array.from(body).buffer : undefined;
204
206
  return new Request(url, {
205
207
  method: req.method,
206
208
  headers: webHeaders,
207
- body: body,
209
+ body: requestBody,
208
210
  });
209
211
  },
210
212
  };
@@ -1 +1 @@
1
- {"version":3,"file":"httpRouter.js","sourceRoot":"","sources":["../../src/server/httpRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"http\";\nimport { parse as parseUrl } from \"url\";\n\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumHTTPDef, HTTPRequest } from \"./defineHTTPRequest.js\";\nimport type { HeliumMiddleware } from \"./middleware.js\";\n\nexport interface HTTPRoute {\n name: string;\n handler: HeliumHTTPDef;\n}\n\nexport class HTTPRouter {\n private routes: Array<{\n method: string;\n pattern: RegExp;\n keys: string[];\n handler: HeliumHTTPDef;\n }> = [];\n private middleware: HeliumMiddleware | null = null;\n private trustProxyDepth: number = 0;\n\n setTrustProxyDepth(depth: number) {\n this.trustProxyDepth = depth;\n }\n\n registerRoutes(routes: HTTPRoute[]) {\n for (const route of routes) {\n const { method, path } = route.handler;\n const { pattern, keys } = pathToRegex(path);\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n keys,\n handler: route.handler,\n });\n }\n }\n\n setMiddleware(middleware: HeliumMiddleware) {\n this.middleware = middleware;\n }\n\n async handleRequest(req: IncomingMessage, res: ServerResponse, ctx?: unknown): Promise<boolean> {\n const method = req.method?.toUpperCase() || \"GET\";\n const url = parseUrl(req.url || \"\", true);\n const pathname = url.pathname || \"/\";\n\n for (const route of this.routes) {\n if (route.method !== \"ALL\" && route.method !== method) {\n continue;\n }\n\n const match = pathname.match(route.pattern);\n if (!match) {\n continue;\n }\n\n // Extract path parameters\n const params: Record<string, string> = {};\n for (let i = 0; i < route.keys.length; i++) {\n params[route.keys[i]] = match[i + 1];\n }\n\n try {\n const query: Record<string, string | string[]> = {};\n if (url.query) {\n for (const [key, value] of Object.entries(url.query)) {\n if (value !== undefined) {\n query[key] = value;\n }\n }\n }\n const httpRequest = await createHTTPRequest(req, query, params);\n\n let result: any;\n // Build context with request metadata\n const ip = extractClientIP(req, this.trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n ...(ctx as Record<string, unknown>),\n };\n\n // Execute middleware if present\n if (this.middleware) {\n let nextCalled = false;\n await this.middleware.handler(\n {\n ctx: httpCtx,\n type: \"http\",\n httpMethod: method,\n httpPath: pathname,\n },\n async () => {\n nextCalled = true;\n result = await route.handler.handler(httpRequest, httpCtx);\n }\n );\n\n // If next() was not called, the middleware blocked the request\n if (!nextCalled) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Request blocked by middleware\" }));\n return true;\n }\n } else {\n // No middleware, execute handler directly\n result = await route.handler.handler(httpRequest, httpCtx);\n }\n\n if (isWebResponse(result)) {\n res.statusCode = result.status;\n result.headers.forEach((value: string, key: string) => {\n res.setHeader(key, value);\n });\n\n if (result.body) {\n const arrayBuf = await result.arrayBuffer();\n res.end(Buffer.from(arrayBuf));\n } else {\n res.end();\n }\n return true;\n }\n\n // Send response\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(result));\n return true;\n } catch (error) {\n log(\"error\", \"Error handling request:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal server error\" }));\n return true;\n }\n }\n\n return false; // No route matched\n }\n}\n\nfunction pathToRegex(path: string): { pattern: RegExp; keys: string[] } {\n const keys: string[] = [];\n const multiSegmentToken = \"__WILDCARD_MULTI__\";\n const pattern = path\n .replace(/\\/\\*\\*/g, `/${multiSegmentToken}`)\n .replace(/\\/:([^/]+)/g, (_, key) => {\n keys.push(key);\n return \"/([^/]+)\";\n })\n // * matches a single path segment, /** matches across segments.\n .replace(/\\*/g, \"[^/]*\")\n .replace(new RegExp(multiSegmentToken, \"g\"), \".*\")\n .replace(/\\//g, \"\\\\/\");\n\n return {\n pattern: new RegExp(`^${pattern}$`),\n keys,\n };\n}\n\nasync function createHTTPRequest(req: IncomingMessage, query: Record<string, string | string[]>, params: Record<string, string>): Promise<HTTPRequest> {\n const headers: Record<string, string | string[] | undefined> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n headers[key.toLowerCase()] = value;\n }\n\n const cookies = parseCookies(req.headers.cookie || \"\");\n\n // Normalize query to always be string\n const normalizedQuery: Record<string, string> = {};\n for (const [key, value] of Object.entries(query)) {\n normalizedQuery[key] = Array.isArray(value) ? value[0] : value;\n }\n\n let bodyBuffer: Buffer | null = null;\n const getBody = async (): Promise<Buffer> => {\n if (bodyBuffer === null) {\n bodyBuffer = await readBody(req);\n }\n return bodyBuffer;\n };\n\n return {\n method: req.method || \"GET\",\n path: req.url || \"/\",\n headers,\n query: normalizedQuery,\n params,\n cookies,\n json: async () => {\n const body = await getBody();\n try {\n return JSON.parse(body.toString(\"utf-8\"));\n } catch {\n throw new Error(\"Invalid JSON in request body\");\n }\n },\n text: async () => {\n const body = await getBody();\n return body.toString(\"utf-8\");\n },\n formData: async () => {\n throw new Error(\"FormData not yet implemented\");\n },\n /**\n * Convert the normalized HTTPRequest into a standard Web `Request`.\n * This mirrors the shape used in defineHTTPRequest's interface and\n * is useful for passing the request into code that expects the Web\n * Fetch Request API (for example third-party handlers or libraries).\n */\n toWebRequest: async () => {\n const protocol = (req.headers[\"x-forwarded-proto\"] as string) || \"http\";\n const host = (req.headers[\"host\"] as string) || \"localhost\";\n const url = `${protocol}://${host}${req.url || \"/\"}`;\n\n const webHeaders = new Headers();\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n for (const v of value) {\n webHeaders.append(key, v);\n }\n } else {\n webHeaders.set(key, value);\n }\n }\n\n const body = req.method !== \"GET\" && req.method !== \"HEAD\" ? await getBody() : undefined;\n\n return new Request(url, {\n method: req.method,\n headers: webHeaders,\n body: body as any,\n });\n },\n };\n}\n\nfunction readBody(req: IncomingMessage, maxBytes: number = 1_048_576): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let totalSize = 0;\n req.on(\"data\", (chunk) => {\n totalSize += chunk.length;\n if (totalSize > maxBytes) {\n req.destroy();\n reject(new Error(\"Request entity too large\"));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n\nfunction parseCookies(cookieHeader: string): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!cookieHeader) {\n return cookies;\n }\n\n const pairs = cookieHeader.split(\";\");\n for (const pair of pairs) {\n const [key, value] = pair.split(\"=\").map((s) => s.trim());\n if (key && value) {\n try {\n cookies[key] = decodeURIComponent(value);\n } catch {\n // Malformed encoding (e.g. %ZZ) — use raw value\n cookies[key] = value;\n }\n }\n }\n return cookies;\n}\n\n/**\n * Detect a Web `Response` object using duck-typing instead of `instanceof`.\n *\n * In Vite's SSR environment the handler code runs inside a separate module\n * context (`ssrLoadModule`), so the `Response` constructor available there\n * may be a *different reference* than the global `Response` that\n * `httpRouter.ts` sees. The classic `instanceof Response` check therefore\n * fails, causing the framework to fall through to `JSON.stringify(result)`\n * which serialises a Response into a tiny broken payload (~126 bytes).\n *\n * By checking for the characteristic properties (`status`, `headers` as a\n * `Headers`-like object, and `arrayBuffer` method) we reliably detect\n * Response objects regardless of which realm they were created in.\n */\nfunction isWebResponse(value: unknown): value is Response {\n if (value instanceof Response) {\n return true;\n }\n\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.status === \"number\" &&\n typeof candidate.arrayBuffer === \"function\" &&\n typeof candidate.headers === \"object\" &&\n candidate.headers !== null &&\n typeof (candidate.headers as Record<string, unknown>).forEach === \"function\"\n );\n}\n"]}
1
+ {"version":3,"file":"httpRouter.js","sourceRoot":"","sources":["../../src/server/httpRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"http\";\nimport { parse as parseUrl } from \"url\";\n\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumHTTPDef, HTTPRequest } from \"./defineHTTPRequest.js\";\nimport type { HeliumMiddleware } from \"./middleware.js\";\n\nexport interface HTTPRoute {\n name: string;\n handler: HeliumHTTPDef;\n}\n\ninterface HTTPRouterOptions {\n maxBodySize?: number;\n}\n\nexport class HTTPRouter {\n private routes: Array<{\n method: string;\n pattern: RegExp;\n keys: string[];\n handler: HeliumHTTPDef;\n }> = [];\n private middleware: HeliumMiddleware | null = null;\n private trustProxyDepth: number = 0;\n private maxBodySize: number;\n\n constructor(options: HTTPRouterOptions = {}) {\n this.maxBodySize = options.maxBodySize ?? 1_048_576;\n }\n\n setTrustProxyDepth(depth: number) {\n this.trustProxyDepth = depth;\n }\n\n registerRoutes(routes: HTTPRoute[]) {\n for (const route of routes) {\n const { method, path } = route.handler;\n const { pattern, keys } = pathToRegex(path);\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n keys,\n handler: route.handler,\n });\n }\n }\n\n setMiddleware(middleware: HeliumMiddleware) {\n this.middleware = middleware;\n }\n\n async handleRequest(req: IncomingMessage, res: ServerResponse, ctx?: unknown): Promise<boolean> {\n const method = req.method?.toUpperCase() || \"GET\";\n const url = parseUrl(req.url || \"\", true);\n const pathname = url.pathname || \"/\";\n\n for (const route of this.routes) {\n if (route.method !== \"ALL\" && route.method !== method) {\n continue;\n }\n\n const match = pathname.match(route.pattern);\n if (!match) {\n continue;\n }\n\n // Extract path parameters\n const params: Record<string, string> = {};\n for (let i = 0; i < route.keys.length; i++) {\n params[route.keys[i]] = match[i + 1];\n }\n\n try {\n const query: Record<string, string | string[]> = {};\n if (url.query) {\n for (const [key, value] of Object.entries(url.query)) {\n if (value !== undefined) {\n query[key] = value;\n }\n }\n }\n const httpRequest = await createHTTPRequest(req, query, params, this.maxBodySize);\n\n let result: any;\n // Build context with request metadata\n const ip = extractClientIP(req, this.trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n ...(ctx as Record<string, unknown>),\n };\n\n // Execute middleware if present\n if (this.middleware) {\n let nextCalled = false;\n await this.middleware.handler(\n {\n ctx: httpCtx,\n type: \"http\",\n httpMethod: method,\n httpPath: pathname,\n },\n async () => {\n nextCalled = true;\n result = await route.handler.handler(httpRequest, httpCtx);\n }\n );\n\n // If next() was not called, the middleware blocked the request\n if (!nextCalled) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Request blocked by middleware\" }));\n return true;\n }\n } else {\n // No middleware, execute handler directly\n result = await route.handler.handler(httpRequest, httpCtx);\n }\n\n if (isWebResponse(result)) {\n res.statusCode = result.status;\n result.headers.forEach((value: string, key: string) => {\n res.setHeader(key, value);\n });\n\n if (result.body) {\n const arrayBuf = await result.arrayBuffer();\n res.end(Buffer.from(arrayBuf));\n } else {\n res.end();\n }\n return true;\n }\n\n // Send response\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(result));\n return true;\n } catch (error) {\n log(\"error\", \"Error handling request:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal server error\" }));\n return true;\n }\n }\n\n return false; // No route matched\n }\n}\n\nfunction pathToRegex(path: string): { pattern: RegExp; keys: string[] } {\n const keys: string[] = [];\n const multiSegmentToken = \"__WILDCARD_MULTI__\";\n const pattern = path\n .replace(/\\/\\*\\*/g, `/${multiSegmentToken}`)\n .replace(/\\/:([^/]+)/g, (_, key) => {\n keys.push(key);\n return \"/([^/]+)\";\n })\n // * matches a single path segment, /** matches across segments.\n .replace(/\\*/g, \"[^/]*\")\n .replace(new RegExp(multiSegmentToken, \"g\"), \".*\")\n .replace(/\\//g, \"\\\\/\");\n\n return {\n pattern: new RegExp(`^${pattern}$`),\n keys,\n };\n}\n\nasync function createHTTPRequest(req: IncomingMessage, query: Record<string, string | string[]>, params: Record<string, string>, maxBodySize: number): Promise<HTTPRequest> {\n const headers: Record<string, string | string[] | undefined> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n headers[key.toLowerCase()] = value;\n }\n\n const cookies = parseCookies(req.headers.cookie || \"\");\n\n // Normalize query to always be string\n const normalizedQuery: Record<string, string> = {};\n for (const [key, value] of Object.entries(query)) {\n normalizedQuery[key] = Array.isArray(value) ? value[0] : value;\n }\n\n let bodyBuffer: Buffer | null = null;\n const getBody = async (): Promise<Buffer> => {\n if (bodyBuffer === null) {\n bodyBuffer = await readBody(req, maxBodySize);\n }\n return bodyBuffer;\n };\n\n return {\n method: req.method || \"GET\",\n path: req.url || \"/\",\n headers,\n query: normalizedQuery,\n params,\n cookies,\n json: async () => {\n const body = await getBody();\n try {\n return JSON.parse(body.toString(\"utf-8\"));\n } catch {\n throw new Error(\"Invalid JSON in request body\");\n }\n },\n text: async () => {\n const body = await getBody();\n return body.toString(\"utf-8\");\n },\n formData: async () => {\n throw new Error(\"FormData not yet implemented\");\n },\n /**\n * Convert the normalized HTTPRequest into a standard Web `Request`.\n * This mirrors the shape used in defineHTTPRequest's interface and\n * is useful for passing the request into code that expects the Web\n * Fetch Request API (for example third-party handlers or libraries).\n */\n toWebRequest: async () => {\n const protocol = (req.headers[\"x-forwarded-proto\"] as string) || \"http\";\n const host = (req.headers[\"host\"] as string) || \"localhost\";\n const url = `${protocol}://${host}${req.url || \"/\"}`;\n\n const webHeaders = new Headers();\n for (const [key, value] of Object.entries(headers)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n for (const v of value) {\n webHeaders.append(key, v);\n }\n } else {\n webHeaders.set(key, value);\n }\n }\n\n const body = req.method !== \"GET\" && req.method !== \"HEAD\" ? await getBody() : undefined;\n const requestBody = body ? Uint8Array.from(body).buffer : undefined;\n\n return new Request(url, {\n method: req.method,\n headers: webHeaders,\n body: requestBody,\n });\n },\n };\n}\n\nfunction readBody(req: IncomingMessage, maxBytes: number = 1_048_576): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let totalSize = 0;\n req.on(\"data\", (chunk) => {\n totalSize += chunk.length;\n if (totalSize > maxBytes) {\n req.destroy();\n reject(new Error(\"Request entity too large\"));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\n req.on(\"error\", reject);\n });\n}\n\nfunction parseCookies(cookieHeader: string): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!cookieHeader) {\n return cookies;\n }\n\n const pairs = cookieHeader.split(\";\");\n for (const pair of pairs) {\n const [key, value] = pair.split(\"=\").map((s) => s.trim());\n if (key && value) {\n try {\n cookies[key] = decodeURIComponent(value);\n } catch {\n // Malformed encoding (e.g. %ZZ) — use raw value\n cookies[key] = value;\n }\n }\n }\n return cookies;\n}\n\n/**\n * Detect a Web `Response` object using duck-typing instead of `instanceof`.\n *\n * In Vite's SSR environment the handler code runs inside a separate module\n * context (`ssrLoadModule`), so the `Response` constructor available there\n * may be a *different reference* than the global `Response` that\n * `httpRouter.ts` sees. The classic `instanceof Response` check therefore\n * fails, causing the framework to fall through to `JSON.stringify(result)`\n * which serialises a Response into a tiny broken payload (~126 bytes).\n *\n * By checking for the characteristic properties (`status`, `headers` as a\n * `Headers`-like object, and `arrayBuffer` method) we reliably detect\n * Response objects regardless of which realm they were created in.\n */\nfunction isWebResponse(value: unknown): value is Response {\n if (value instanceof Response) {\n return true;\n }\n\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.status === \"number\" &&\n typeof candidate.arrayBuffer === \"function\" &&\n typeof candidate.headers === \"object\" &&\n candidate.headers !== null &&\n typeof (candidate.headers as Record<string, unknown>).forEach === \"function\"\n );\n}\n"]}
@@ -45,7 +45,7 @@ export function startProdServer(options) {
45
45
  // Initialize rate limiter
46
46
  const rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);
47
47
  const registry = new RpcRegistry();
48
- const httpRouter = new HTTPRouter();
48
+ const httpRouter = new HTTPRouter({ maxBodySize: rpcConfig.maxBodySize });
49
49
  const seoRouter = new SEOMetadataRouter();
50
50
  httpRouter.setTrustProxyDepth(trustProxyDepth);
51
51
  registerHandlers(registry, httpRouter, seoRouter);
@@ -1 +1 @@
1
- {"version":3,"file":"prodServer.js","sourceRoot":"","sources":["../../src/server/prodServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode as msgpackEncode } from \"@msgpack/msgpack\";\nimport fs from \"fs\";\nimport http from \"http\";\nimport path from \"path\";\nimport { promisify } from \"util\";\nimport type WebSocket from \"ws\";\nimport { WebSocketServer } from \"ws\";\nimport { brotliCompress, deflate, gzip } from \"zlib\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumConfig } from \"./config.js\";\nimport { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from \"./config.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumWorkerDef } from \"./defineWorker.js\";\nimport { startWorker, stopAllWorkers } from \"./defineWorker.js\";\nimport { HTTPRouter } from \"./httpRouter.js\";\nimport { injectSocialMetaIntoHtml, loadDefaultSocialMetaFromHtmlFile } from \"./meta.js\";\nimport { RateLimiter } from \"./rateLimiter.js\";\nimport { RpcRegistry } from \"./rpcRegistry.js\";\nimport { generateConnectionToken, initializeSecurity, verifyConnectionToken } from \"./security.js\";\nimport { SEOMetadataRouter } from \"./seoMetadataRouter.js\";\nimport { prepareForMsgpack } from \"./serializer.js\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\nconst brotliCompressAsync = promisify(brotliCompress);\n\ninterface WorkerEntry {\n name: string;\n worker: HeliumWorkerDef;\n}\n\ninterface ProdServerOptions {\n port?: number;\n distDir?: string;\n staticDir?: string;\n registerHandlers: (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;\n config?: HeliumConfig;\n workers?: WorkerEntry[];\n}\n\n/**\n * Starts a production HTTP server that:\n * - Serves static files from the dist directory\n * - Supports SSG (Static Site Generation) by serving .html files for routes (e.g., /about -> about.html)\n * - Falls back to index.html for client-side routing (SPA)\n * - Handles custom HTTP endpoints (webhooks, auth, etc.)\n * - Hosts WebSocket RPC server\n * - Starts background workers\n *\n * SSG Behavior:\n * - Production correctly serves SSG pages (e.g., /about serves about.html with pre-rendered content)\n * - This ensures search engines and social media crawlers see the correct content\n * - Client-side navigation between pages still works via React Router\n */\nexport function startProdServer(options: ProdServerOptions) {\n const { port = Number(process.env.PORT || 3000), distDir = \"dist\", staticDir = path.resolve(process.cwd(), distDir), registerHandlers, config = {}, workers = [] } = options;\n\n // Load configuration\n const trustProxyDepth = getTrustProxyDepth(config);\n const rpcSecurity = getRpcSecurityConfig(config);\n const rpcConfig = getRpcConfig(config);\n const compressionConfig = rpcConfig.compression;\n initializeSecurity(rpcSecurity);\n\n // Initialize rate limiter\n const rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);\n\n const registry = new RpcRegistry();\n const httpRouter = new HTTPRouter();\n const seoRouter = new SEOMetadataRouter();\n httpRouter.setTrustProxyDepth(trustProxyDepth);\n registerHandlers(registry, httpRouter, seoRouter);\n registry.setRateLimiter(rateLimiter);\n registry.setMaxBatchSize(rpcConfig.maxBatchSize);\n\n // Security: max body size for HTTP requests (1 MB default)\n const maxBodySize = rpcConfig.maxBodySize ?? 1_048_576;\n let cachedDefaultMeta: Awaited<ReturnType<typeof loadDefaultSocialMetaFromHtmlFile>> | undefined;\n\n const getDefaultMeta = async () => {\n if (cachedDefaultMeta !== undefined) {\n return cachedDefaultMeta;\n }\n\n cachedDefaultMeta = await loadDefaultSocialMetaFromHtmlFile(path.join(staticDir, \"index.html\"));\n return cachedDefaultMeta;\n };\n\n registry.register(SEO_METADATA_RPC_METHOD, {\n __kind: \"method\",\n __id: SEO_METADATA_RPC_METHOD,\n handler: async (args: { path?: string } | undefined, ctx: HeliumContext) => {\n const requestedPath = typeof args?.path === \"string\" ? args.path : \"/\";\n const targetPath = requestedPath.startsWith(\"/\") ? requestedPath : `/${requestedPath}`;\n const metadata = await seoRouter.resolve(ctx.req.raw, ctx, targetPath);\n return metadata ?? (await getDefaultMeta());\n },\n });\n\n // Create HTTP server\n const server = http.createServer(async (req, res) => {\n // Apply security headers to all responses\n setSecurityHeaders(res, config);\n\n // Handle CORS preflight\n if (req.method === \"OPTIONS\") {\n handleCorsHeaders(req, res, config);\n res.writeHead(204);\n res.end();\n return;\n }\n handleCorsHeaders(req, res, config);\n\n // Handle token refresh endpoint\n if (req.url === \"/__helium__/refresh-token\") {\n // Security: only allow POST to prevent CSRF via <img>/<script> tags\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n // Security: require custom header to prevent cross-origin requests\n if (!req.headers[\"x-requested-with\"]) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Forbidden\" }));\n return;\n }\n const token = generateConnectionToken();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ token }));\n return;\n }\n\n // Handle HTTP-based RPC endpoint (alternative to WebSocket for mobile networks)\n if (req.url === \"/__helium__/rpc\" && req.method === \"POST\") {\n // Security: verify connection token for HTTP RPC\n const authToken = req.headers[\"x-helium-token\"] as string | undefined;\n if (!authToken || !verifyConnectionToken(authToken)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Unauthorized\" }));\n return;\n }\n\n // Security: check Content-Length before reading body\n const contentLength = parseInt(req.headers[\"content-length\"] || \"0\", 10);\n if (contentLength > maxBodySize) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n let aborted = false;\n req.on(\"data\", (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > maxBodySize) {\n aborted = true;\n req.destroy();\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", async () => {\n if (aborted) {\n return;\n }\n try {\n const body = Buffer.concat(chunks);\n const ip = extractClientIP(req, trustProxyDepth);\n const result = await registry.handleHttpRequest(body, ip, req);\n\n const encoded = msgpackEncode(prepareForMsgpack(result.response));\n let responseBody = Buffer.from(encoded as Uint8Array);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/msgpack\",\n \"Cache-Control\": \"no-store\",\n };\n\n // Handle compression\n const acceptEncoding = req.headers[\"accept-encoding\"] as string;\n if (acceptEncoding && responseBody.length > 1024) {\n if (acceptEncoding.includes(\"br\")) {\n responseBody = await brotliCompressAsync(responseBody);\n headers[\"Content-Encoding\"] = \"br\";\n } else if (acceptEncoding.includes(\"gzip\")) {\n responseBody = await gzipAsync(responseBody);\n headers[\"Content-Encoding\"] = \"gzip\";\n } else if (acceptEncoding.includes(\"deflate\")) {\n responseBody = await deflateAsync(responseBody);\n headers[\"Content-Encoding\"] = \"deflate\";\n }\n }\n\n res.writeHead(200, headers);\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"HTTP RPC error:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Internal server error\" }));\n }\n });\n return;\n }\n\n // Try HTTP handlers first (webhooks, auth, etc.)\n const handled = await httpRouter.handleRequest(req, res);\n if (handled) {\n return;\n }\n\n // Serve static files\n const url = req.url || \"/\";\n\n // Block access to sensitive configuration and server files\n const blockedFiles = [\"helium.config.js\", \"helium.config.mjs\", \"helium.config.ts\", \"server.js\", \".env\", \".env.local\", \".env.production\"];\n\n const requestedFile = path.basename(url.split(\"?\")[0]);\n let filePath: string = path.join(staticDir, \"index.html\");\n let is404 = false;\n\n if (blockedFiles.some((blocked) => requestedFile === blocked || requestedFile.startsWith(\".env\"))) {\n // Serve index.html so the SPA router can render the 404 page\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n } else {\n // Clean URL (remove query params and trailing slash)\n const cleanUrl = url.split(\"?\")[0].replace(/\\/$/, \"\") || \"/\";\n\n // Security: path traversal prevention — resolve and verify\n const resolvedStaticDir = path.resolve(staticDir);\n const candidatePath = path.resolve(staticDir, \".\" + cleanUrl);\n if (!candidatePath.startsWith(resolvedStaticDir + path.sep) && candidatePath !== resolvedStaticDir) {\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n }\n\n // Try different file paths for SSG support\n if (!is404 && cleanUrl === \"/\") {\n // Try index.ssg.html first (if root page has SSG)\n const ssgIndexPath = path.join(staticDir, \"index.ssg.html\");\n if (fs.existsSync(ssgIndexPath)) {\n filePath = ssgIndexPath;\n } else {\n filePath = path.join(staticDir, \"index.html\");\n }\n } else if (!is404) {\n // If cleanUrl has no extension, prioritize .html files for SSG pages\n if (!path.extname(cleanUrl)) {\n const htmlPath = path.join(staticDir, cleanUrl + \".html\");\n if (fs.existsSync(htmlPath)) {\n filePath = htmlPath;\n } else {\n // Fall back to exact path (for assets or directories)\n filePath = path.join(staticDir, cleanUrl);\n }\n } else {\n // Has an extension, try exact path (for assets like /assets/main.js)\n filePath = path.join(staticDir, cleanUrl);\n }\n }\n\n // If file doesn't exist or is a directory, fall back to index.html for SPA routing\n const isFileOrExists = !is404 && filePath && fs.existsSync(filePath) && fs.statSync(filePath).isFile();\n if (!isFileOrExists && !url.startsWith(\"/api\") && !url.startsWith(\"/webhooks\") && !url.startsWith(\"/auth\")) {\n // Fall back to index.html for SPA routing\n // Note: We don't set is404 here because the client-side router will determine\n // if the route exists. If it doesn't, the router will render the 404 page.\n filePath = path.join(staticDir, \"index.html\");\n // Don't set is404 = true here - let the client-side router handle it\n }\n }\n\n // Check if file exists (should always exist now since we fallback to index.html)\n if (!fs.existsSync(filePath)) {\n // This should rarely happen - only if index.html itself is missing\n res.writeHead(404, { \"Content-Type\": \"text/html\" });\n res.end(\"Not found\");\n return;\n }\n\n // Determine content type\n const ext = path.extname(filePath);\n const contentTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".eot\": \"application/vnd.ms-fontobject\",\n };\n const contentType = contentTypes[ext] || \"application/octet-stream\";\n\n try {\n const content = fs.readFileSync(filePath);\n let responseBody = content;\n\n if (!is404 && contentType === \"text/html\") {\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n const metadata = await seoRouter.resolve(req, httpCtx);\n if (metadata) {\n const html = content.toString(\"utf-8\");\n responseBody = Buffer.from(injectSocialMetaIntoHtml(html, metadata), \"utf-8\");\n }\n }\n\n // Set status code to 404 if serving the 404 page\n const statusCode = is404 ? 404 : 200;\n res.writeHead(statusCode, { \"Content-Type\": contentType });\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"Error serving file:\", error);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal server error\");\n }\n });\n\n // Setup WebSocket server for RPC\n const wss = new WebSocketServer({\n noServer: true,\n maxPayload: rpcConfig.maxWsPayload,\n perMessageDeflate: compressionConfig.enabled\n ? {\n zlibDeflateOptions: {\n chunkSize: 1024,\n memLevel: 7,\n level: 9, // 6 is default compression level (balanced)\n },\n zlibInflateOptions: {\n chunkSize: 10 * 1024,\n },\n threshold: compressionConfig.threshold,\n }\n : false,\n });\n\n wss.on(\"connection\", (socket: WebSocket, req: http.IncomingMessage) => {\n // Extract client IP with proxy configuration\n const ip = extractClientIP(req, trustProxyDepth);\n\n // Store connection metadata for RPC context\n registry.setSocketMetadata(socket, ip, req);\n\n // Track connection and check IP limit\n if (!rateLimiter.trackConnection(socket, ip)) {\n socket.close(1008, \"Too many connections from your IP\");\n return;\n }\n\n // Prevent unhandled errors from crashing the process (e.g. maxPayload exceeded)\n socket.on(\"error\", (err) => {\n log(\"warn\", \"WebSocket error:\", err);\n if (socket.readyState === socket.OPEN || socket.readyState === socket.CLOSING) {\n socket.close(1009, \"Message too large\");\n }\n });\n\n socket.on(\"message\", (msg: WebSocket.RawData, _isBinary: boolean) => {\n // Check rate limit\n if (!rateLimiter.checkRateLimit(socket)) {\n // Parse request to get the ID for proper error response\n try {\n let req: any;\n // Always expect MessagePack\n const buffer = Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any);\n const { decode: msgpackDecode } = require(\"@msgpack/msgpack\");\n req = msgpackDecode(buffer);\n\n const stats = rateLimiter.getConnectionStats(socket);\n const now = Date.now();\n const resetInSeconds = stats ? Math.ceil((stats.resetTimeMs - now) / 1000) : 0;\n\n const createError = (id: string) => ({\n id,\n ok: false,\n stats: {\n remainingRequests: stats ? stats.remainingMessages : 0,\n resetInSeconds,\n },\n error: \"Rate limit exceeded\",\n });\n\n let errorResponse: any;\n if (Array.isArray(req)) {\n errorResponse = req.map((r: any) => createError(r.id));\n } else {\n errorResponse = createError(req.id);\n }\n\n log(\"warn\", `Rate limit exceeded for IP ${ip}, resets in ${resetInSeconds} seconds`);\n socket.send(msgpackEncode(errorResponse) as Buffer);\n } catch {\n // If we can't parse the request, just close the connection\n socket.close();\n }\n return;\n }\n\n registry.handleMessage(socket, Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any));\n });\n });\n\n // Handle WebSocket upgrade requests\n server.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/rpc\")) {\n // Security: read token from Sec-WebSocket-Protocol header instead of query string\n const protocols = req.headers[\"sec-websocket-protocol\"];\n const token =\n typeof protocols === \"string\"\n ? protocols\n .split(\",\")\n .map((p) => p.trim())\n .find((p) => p.includes(\".\"))\n : undefined;\n\n if (!token || !verifyConnectionToken(token)) {\n log(\"warn\", \"WebSocket connection rejected - invalid token\");\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n // Check IP connection limit before upgrading\n const ip = extractClientIP(req, trustProxyDepth);\n if (rpcSecurity.maxConnectionsPerIP > 0) {\n const currentConnections = rateLimiter.getIPConnectionCount(ip);\n if (currentConnections >= rpcSecurity.maxConnectionsPerIP) {\n log(\"warn\", `WebSocket connection rejected - IP ${ip} has ${currentConnections} connections`);\n socket.write(\"HTTP/1.1 429 Too Many Requests\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n\n // Start server\n server.listen(port, () => {\n log(\"info\", `Production server listening on http://localhost:${port}`);\n log(\"info\", `Serving static files from ${staticDir}`);\n log(\"info\", `WebSocket RPC available at ws://localhost:${port}/rpc`);\n\n // Start workers\n if (workers.length > 0) {\n log(\"info\", `Starting ${workers.length} worker(s)...`);\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n }\n });\n\n // Handle graceful shutdown\n const shutdown = async () => {\n log(\"info\", \"Shutting down...\");\n await stopAllWorkers();\n server.close(() => {\n log(\"info\", \"Server closed\");\n process.exit(0);\n });\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n return server;\n}\n\n// ============================================================================\n// Security helper functions\n// ============================================================================\n\n/**\n * Set default security headers on every HTTP response.\n */\nfunction setSecurityHeaders(res: http.ServerResponse, config: HeliumConfig): void {\n res.setHeader(\"X-Content-Type-Options\", \"nosniff\");\n res.setHeader(\"X-Frame-Options\", \"DENY\");\n res.setHeader(\"X-XSS-Protection\", \"0\");\n res.setHeader(\"Referrer-Policy\", \"strict-origin-when-cross-origin\");\n res.setHeader(\"Permissions-Policy\", \"camera=(), microphone=(), geolocation=()\");\n\n const csp = config.security?.contentSecurityPolicy;\n if (csp) {\n res.setHeader(\"Content-Security-Policy\", csp);\n }\n\n if (config.security?.hsts !== false) {\n res.setHeader(\"Strict-Transport-Security\", \"max-age=31536000; includeSubDomains\");\n }\n}\n\n/**\n * Handle CORS headers based on configuration.\n * Default: restrict to same-origin (no CORS header = browser blocks cross-origin).\n */\nfunction handleCorsHeaders(req: http.IncomingMessage, res: http.ServerResponse, config: HeliumConfig): void {\n const allowedOrigins = config.security?.corsOrigins;\n if (!allowedOrigins || allowedOrigins.length === 0) {\n // No CORS configured — same-origin only by default\n return;\n }\n\n const origin = req.headers.origin;\n if (!origin) {\n return;\n }\n\n const isAllowed = allowedOrigins.includes(\"*\") || allowedOrigins.includes(origin);\n if (isAllowed) {\n res.setHeader(\"Access-Control-Allow-Origin\", allowedOrigins.includes(\"*\") ? \"*\" : origin);\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, X-Requested-With, X-Helium-Token\");\n res.setHeader(\"Access-Control-Max-Age\", \"86400\");\n\n if (!allowedOrigins.includes(\"*\")) {\n res.setHeader(\"Vary\", \"Origin\");\n }\n }\n}\n"]}
1
+ {"version":3,"file":"prodServer.js","sourceRoot":"","sources":["../../src/server/prodServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode as msgpackEncode } from \"@msgpack/msgpack\";\nimport fs from \"fs\";\nimport http from \"http\";\nimport path from \"path\";\nimport { promisify } from \"util\";\nimport type WebSocket from \"ws\";\nimport { WebSocketServer } from \"ws\";\nimport { brotliCompress, deflate, gzip } from \"zlib\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumConfig } from \"./config.js\";\nimport { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from \"./config.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumWorkerDef } from \"./defineWorker.js\";\nimport { startWorker, stopAllWorkers } from \"./defineWorker.js\";\nimport { HTTPRouter } from \"./httpRouter.js\";\nimport { injectSocialMetaIntoHtml, loadDefaultSocialMetaFromHtmlFile } from \"./meta.js\";\nimport { RateLimiter } from \"./rateLimiter.js\";\nimport { RpcRegistry } from \"./rpcRegistry.js\";\nimport { generateConnectionToken, initializeSecurity, verifyConnectionToken } from \"./security.js\";\nimport { SEOMetadataRouter } from \"./seoMetadataRouter.js\";\nimport { prepareForMsgpack } from \"./serializer.js\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\nconst brotliCompressAsync = promisify(brotliCompress);\n\ninterface WorkerEntry {\n name: string;\n worker: HeliumWorkerDef;\n}\n\ninterface ProdServerOptions {\n port?: number;\n distDir?: string;\n staticDir?: string;\n registerHandlers: (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;\n config?: HeliumConfig;\n workers?: WorkerEntry[];\n}\n\n/**\n * Starts a production HTTP server that:\n * - Serves static files from the dist directory\n * - Supports SSG (Static Site Generation) by serving .html files for routes (e.g., /about -> about.html)\n * - Falls back to index.html for client-side routing (SPA)\n * - Handles custom HTTP endpoints (webhooks, auth, etc.)\n * - Hosts WebSocket RPC server\n * - Starts background workers\n *\n * SSG Behavior:\n * - Production correctly serves SSG pages (e.g., /about serves about.html with pre-rendered content)\n * - This ensures search engines and social media crawlers see the correct content\n * - Client-side navigation between pages still works via React Router\n */\nexport function startProdServer(options: ProdServerOptions) {\n const { port = Number(process.env.PORT || 3000), distDir = \"dist\", staticDir = path.resolve(process.cwd(), distDir), registerHandlers, config = {}, workers = [] } = options;\n\n // Load configuration\n const trustProxyDepth = getTrustProxyDepth(config);\n const rpcSecurity = getRpcSecurityConfig(config);\n const rpcConfig = getRpcConfig(config);\n const compressionConfig = rpcConfig.compression;\n initializeSecurity(rpcSecurity);\n\n // Initialize rate limiter\n const rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);\n\n const registry = new RpcRegistry();\n const httpRouter = new HTTPRouter({ maxBodySize: rpcConfig.maxBodySize });\n const seoRouter = new SEOMetadataRouter();\n httpRouter.setTrustProxyDepth(trustProxyDepth);\n registerHandlers(registry, httpRouter, seoRouter);\n registry.setRateLimiter(rateLimiter);\n registry.setMaxBatchSize(rpcConfig.maxBatchSize);\n\n // Security: max body size for HTTP requests (1 MB default)\n const maxBodySize = rpcConfig.maxBodySize ?? 1_048_576;\n let cachedDefaultMeta: Awaited<ReturnType<typeof loadDefaultSocialMetaFromHtmlFile>> | undefined;\n\n const getDefaultMeta = async () => {\n if (cachedDefaultMeta !== undefined) {\n return cachedDefaultMeta;\n }\n\n cachedDefaultMeta = await loadDefaultSocialMetaFromHtmlFile(path.join(staticDir, \"index.html\"));\n return cachedDefaultMeta;\n };\n\n registry.register(SEO_METADATA_RPC_METHOD, {\n __kind: \"method\",\n __id: SEO_METADATA_RPC_METHOD,\n handler: async (args: { path?: string } | undefined, ctx: HeliumContext) => {\n const requestedPath = typeof args?.path === \"string\" ? args.path : \"/\";\n const targetPath = requestedPath.startsWith(\"/\") ? requestedPath : `/${requestedPath}`;\n const metadata = await seoRouter.resolve(ctx.req.raw, ctx, targetPath);\n return metadata ?? (await getDefaultMeta());\n },\n });\n\n // Create HTTP server\n const server = http.createServer(async (req, res) => {\n // Apply security headers to all responses\n setSecurityHeaders(res, config);\n\n // Handle CORS preflight\n if (req.method === \"OPTIONS\") {\n handleCorsHeaders(req, res, config);\n res.writeHead(204);\n res.end();\n return;\n }\n handleCorsHeaders(req, res, config);\n\n // Handle token refresh endpoint\n if (req.url === \"/__helium__/refresh-token\") {\n // Security: only allow POST to prevent CSRF via <img>/<script> tags\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n // Security: require custom header to prevent cross-origin requests\n if (!req.headers[\"x-requested-with\"]) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Forbidden\" }));\n return;\n }\n const token = generateConnectionToken();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ token }));\n return;\n }\n\n // Handle HTTP-based RPC endpoint (alternative to WebSocket for mobile networks)\n if (req.url === \"/__helium__/rpc\" && req.method === \"POST\") {\n // Security: verify connection token for HTTP RPC\n const authToken = req.headers[\"x-helium-token\"] as string | undefined;\n if (!authToken || !verifyConnectionToken(authToken)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Unauthorized\" }));\n return;\n }\n\n // Security: check Content-Length before reading body\n const contentLength = parseInt(req.headers[\"content-length\"] || \"0\", 10);\n if (contentLength > maxBodySize) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n let aborted = false;\n req.on(\"data\", (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > maxBodySize) {\n aborted = true;\n req.destroy();\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", async () => {\n if (aborted) {\n return;\n }\n try {\n const body = Buffer.concat(chunks);\n const ip = extractClientIP(req, trustProxyDepth);\n const result = await registry.handleHttpRequest(body, ip, req);\n\n const encoded = msgpackEncode(prepareForMsgpack(result.response));\n let responseBody = Buffer.from(encoded as Uint8Array);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/msgpack\",\n \"Cache-Control\": \"no-store\",\n };\n\n // Handle compression\n const acceptEncoding = req.headers[\"accept-encoding\"] as string;\n if (acceptEncoding && responseBody.length > 1024) {\n if (acceptEncoding.includes(\"br\")) {\n responseBody = await brotliCompressAsync(responseBody);\n headers[\"Content-Encoding\"] = \"br\";\n } else if (acceptEncoding.includes(\"gzip\")) {\n responseBody = await gzipAsync(responseBody);\n headers[\"Content-Encoding\"] = \"gzip\";\n } else if (acceptEncoding.includes(\"deflate\")) {\n responseBody = await deflateAsync(responseBody);\n headers[\"Content-Encoding\"] = \"deflate\";\n }\n }\n\n res.writeHead(200, headers);\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"HTTP RPC error:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Internal server error\" }));\n }\n });\n return;\n }\n\n // Try HTTP handlers first (webhooks, auth, etc.)\n const handled = await httpRouter.handleRequest(req, res);\n if (handled) {\n return;\n }\n\n // Serve static files\n const url = req.url || \"/\";\n\n // Block access to sensitive configuration and server files\n const blockedFiles = [\"helium.config.js\", \"helium.config.mjs\", \"helium.config.ts\", \"server.js\", \".env\", \".env.local\", \".env.production\"];\n\n const requestedFile = path.basename(url.split(\"?\")[0]);\n let filePath: string = path.join(staticDir, \"index.html\");\n let is404 = false;\n\n if (blockedFiles.some((blocked) => requestedFile === blocked || requestedFile.startsWith(\".env\"))) {\n // Serve index.html so the SPA router can render the 404 page\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n } else {\n // Clean URL (remove query params and trailing slash)\n const cleanUrl = url.split(\"?\")[0].replace(/\\/$/, \"\") || \"/\";\n\n // Security: path traversal prevention — resolve and verify\n const resolvedStaticDir = path.resolve(staticDir);\n const candidatePath = path.resolve(staticDir, \".\" + cleanUrl);\n if (!candidatePath.startsWith(resolvedStaticDir + path.sep) && candidatePath !== resolvedStaticDir) {\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n }\n\n // Try different file paths for SSG support\n if (!is404 && cleanUrl === \"/\") {\n // Try index.ssg.html first (if root page has SSG)\n const ssgIndexPath = path.join(staticDir, \"index.ssg.html\");\n if (fs.existsSync(ssgIndexPath)) {\n filePath = ssgIndexPath;\n } else {\n filePath = path.join(staticDir, \"index.html\");\n }\n } else if (!is404) {\n // If cleanUrl has no extension, prioritize .html files for SSG pages\n if (!path.extname(cleanUrl)) {\n const htmlPath = path.join(staticDir, cleanUrl + \".html\");\n if (fs.existsSync(htmlPath)) {\n filePath = htmlPath;\n } else {\n // Fall back to exact path (for assets or directories)\n filePath = path.join(staticDir, cleanUrl);\n }\n } else {\n // Has an extension, try exact path (for assets like /assets/main.js)\n filePath = path.join(staticDir, cleanUrl);\n }\n }\n\n // If file doesn't exist or is a directory, fall back to index.html for SPA routing\n const isFileOrExists = !is404 && filePath && fs.existsSync(filePath) && fs.statSync(filePath).isFile();\n if (!isFileOrExists && !url.startsWith(\"/api\") && !url.startsWith(\"/webhooks\") && !url.startsWith(\"/auth\")) {\n // Fall back to index.html for SPA routing\n // Note: We don't set is404 here because the client-side router will determine\n // if the route exists. If it doesn't, the router will render the 404 page.\n filePath = path.join(staticDir, \"index.html\");\n // Don't set is404 = true here - let the client-side router handle it\n }\n }\n\n // Check if file exists (should always exist now since we fallback to index.html)\n if (!fs.existsSync(filePath)) {\n // This should rarely happen - only if index.html itself is missing\n res.writeHead(404, { \"Content-Type\": \"text/html\" });\n res.end(\"Not found\");\n return;\n }\n\n // Determine content type\n const ext = path.extname(filePath);\n const contentTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".eot\": \"application/vnd.ms-fontobject\",\n };\n const contentType = contentTypes[ext] || \"application/octet-stream\";\n\n try {\n const content = fs.readFileSync(filePath);\n let responseBody = content;\n\n if (!is404 && contentType === \"text/html\") {\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n const metadata = await seoRouter.resolve(req, httpCtx);\n if (metadata) {\n const html = content.toString(\"utf-8\");\n responseBody = Buffer.from(injectSocialMetaIntoHtml(html, metadata), \"utf-8\");\n }\n }\n\n // Set status code to 404 if serving the 404 page\n const statusCode = is404 ? 404 : 200;\n res.writeHead(statusCode, { \"Content-Type\": contentType });\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"Error serving file:\", error);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal server error\");\n }\n });\n\n // Setup WebSocket server for RPC\n const wss = new WebSocketServer({\n noServer: true,\n maxPayload: rpcConfig.maxWsPayload,\n perMessageDeflate: compressionConfig.enabled\n ? {\n zlibDeflateOptions: {\n chunkSize: 1024,\n memLevel: 7,\n level: 9, // 6 is default compression level (balanced)\n },\n zlibInflateOptions: {\n chunkSize: 10 * 1024,\n },\n threshold: compressionConfig.threshold,\n }\n : false,\n });\n\n wss.on(\"connection\", (socket: WebSocket, req: http.IncomingMessage) => {\n // Extract client IP with proxy configuration\n const ip = extractClientIP(req, trustProxyDepth);\n\n // Store connection metadata for RPC context\n registry.setSocketMetadata(socket, ip, req);\n\n // Track connection and check IP limit\n if (!rateLimiter.trackConnection(socket, ip)) {\n socket.close(1008, \"Too many connections from your IP\");\n return;\n }\n\n // Prevent unhandled errors from crashing the process (e.g. maxPayload exceeded)\n socket.on(\"error\", (err) => {\n log(\"warn\", \"WebSocket error:\", err);\n if (socket.readyState === socket.OPEN || socket.readyState === socket.CLOSING) {\n socket.close(1009, \"Message too large\");\n }\n });\n\n socket.on(\"message\", (msg: WebSocket.RawData, _isBinary: boolean) => {\n // Check rate limit\n if (!rateLimiter.checkRateLimit(socket)) {\n // Parse request to get the ID for proper error response\n try {\n let req: any;\n // Always expect MessagePack\n const buffer = Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any);\n const { decode: msgpackDecode } = require(\"@msgpack/msgpack\");\n req = msgpackDecode(buffer);\n\n const stats = rateLimiter.getConnectionStats(socket);\n const now = Date.now();\n const resetInSeconds = stats ? Math.ceil((stats.resetTimeMs - now) / 1000) : 0;\n\n const createError = (id: string) => ({\n id,\n ok: false,\n stats: {\n remainingRequests: stats ? stats.remainingMessages : 0,\n resetInSeconds,\n },\n error: \"Rate limit exceeded\",\n });\n\n let errorResponse: any;\n if (Array.isArray(req)) {\n errorResponse = req.map((r: any) => createError(r.id));\n } else {\n errorResponse = createError(req.id);\n }\n\n log(\"warn\", `Rate limit exceeded for IP ${ip}, resets in ${resetInSeconds} seconds`);\n socket.send(msgpackEncode(errorResponse) as Buffer);\n } catch {\n // If we can't parse the request, just close the connection\n socket.close();\n }\n return;\n }\n\n registry.handleMessage(socket, Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any));\n });\n });\n\n // Handle WebSocket upgrade requests\n server.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/rpc\")) {\n // Security: read token from Sec-WebSocket-Protocol header instead of query string\n const protocols = req.headers[\"sec-websocket-protocol\"];\n const token =\n typeof protocols === \"string\"\n ? protocols\n .split(\",\")\n .map((p) => p.trim())\n .find((p) => p.includes(\".\"))\n : undefined;\n\n if (!token || !verifyConnectionToken(token)) {\n log(\"warn\", \"WebSocket connection rejected - invalid token\");\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n // Check IP connection limit before upgrading\n const ip = extractClientIP(req, trustProxyDepth);\n if (rpcSecurity.maxConnectionsPerIP > 0) {\n const currentConnections = rateLimiter.getIPConnectionCount(ip);\n if (currentConnections >= rpcSecurity.maxConnectionsPerIP) {\n log(\"warn\", `WebSocket connection rejected - IP ${ip} has ${currentConnections} connections`);\n socket.write(\"HTTP/1.1 429 Too Many Requests\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n\n // Start server\n server.listen(port, () => {\n log(\"info\", `Production server listening on http://localhost:${port}`);\n log(\"info\", `Serving static files from ${staticDir}`);\n log(\"info\", `WebSocket RPC available at ws://localhost:${port}/rpc`);\n\n // Start workers\n if (workers.length > 0) {\n log(\"info\", `Starting ${workers.length} worker(s)...`);\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n }\n });\n\n // Handle graceful shutdown\n const shutdown = async () => {\n log(\"info\", \"Shutting down...\");\n await stopAllWorkers();\n server.close(() => {\n log(\"info\", \"Server closed\");\n process.exit(0);\n });\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n return server;\n}\n\n// ============================================================================\n// Security helper functions\n// ============================================================================\n\n/**\n * Set default security headers on every HTTP response.\n */\nfunction setSecurityHeaders(res: http.ServerResponse, config: HeliumConfig): void {\n res.setHeader(\"X-Content-Type-Options\", \"nosniff\");\n res.setHeader(\"X-Frame-Options\", \"DENY\");\n res.setHeader(\"X-XSS-Protection\", \"0\");\n res.setHeader(\"Referrer-Policy\", \"strict-origin-when-cross-origin\");\n res.setHeader(\"Permissions-Policy\", \"camera=(), microphone=(), geolocation=()\");\n\n const csp = config.security?.contentSecurityPolicy;\n if (csp) {\n res.setHeader(\"Content-Security-Policy\", csp);\n }\n\n if (config.security?.hsts !== false) {\n res.setHeader(\"Strict-Transport-Security\", \"max-age=31536000; includeSubDomains\");\n }\n}\n\n/**\n * Handle CORS headers based on configuration.\n * Default: restrict to same-origin (no CORS header = browser blocks cross-origin).\n */\nfunction handleCorsHeaders(req: http.IncomingMessage, res: http.ServerResponse, config: HeliumConfig): void {\n const allowedOrigins = config.security?.corsOrigins;\n if (!allowedOrigins || allowedOrigins.length === 0) {\n // No CORS configured — same-origin only by default\n return;\n }\n\n const origin = req.headers.origin;\n if (!origin) {\n return;\n }\n\n const isAllowed = allowedOrigins.includes(\"*\") || allowedOrigins.includes(origin);\n if (isAllowed) {\n res.setHeader(\"Access-Control-Allow-Origin\", allowedOrigins.includes(\"*\") ? \"*\" : origin);\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, X-Requested-With, X-Helium-Token\");\n res.setHeader(\"Access-Control-Max-Age\", \"86400\");\n\n if (!allowedOrigins.includes(\"*\")) {\n res.setHeader(\"Vary\", \"Origin\");\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "heliumts",
3
- "version": "0.7.6",
3
+ "version": "0.7.7",
4
4
  "description": "A lightweight full-stack React framework with file-based routing, RPC, and SSG support",
5
5
  "keywords": [
6
6
  "react",