feat(runtime): add production control-plane foundation
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
} from 'node:http';
|
||||
import { extname, isAbsolute, relative, resolve, sep } from 'node:path';
|
||||
import { pipeline } from 'node:stream/promises';
|
||||
import { GATEWAY_AUTH_HEADER } from './runtime-config.js';
|
||||
|
||||
export const CANARY_DEFAULT_HOST = '127.0.0.1';
|
||||
export const CANARY_DEFAULT_PORT = 8789;
|
||||
@@ -55,6 +56,7 @@ function isNumericLoopback(host: string): boolean {
|
||||
}
|
||||
|
||||
export interface CanaryGatewayOptions {
|
||||
readonly gatewayToken?: string;
|
||||
readonly distDir: string;
|
||||
readonly host?: string;
|
||||
readonly port?: number;
|
||||
@@ -87,6 +89,16 @@ function withoutHopByHop(headers: IncomingHttpHeaders): IncomingHttpHeaders {
|
||||
);
|
||||
}
|
||||
|
||||
function trustedUpstreamHeaders(
|
||||
headers: IncomingHttpHeaders,
|
||||
gatewayToken: string | undefined,
|
||||
): IncomingHttpHeaders {
|
||||
const sanitized = withoutHopByHop(headers);
|
||||
delete sanitized[GATEWAY_AUTH_HEADER];
|
||||
if (gatewayToken !== undefined) sanitized[GATEWAY_AUTH_HEADER] = gatewayToken;
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
function isProxyPath(pathname: string): boolean {
|
||||
return pathname === '/healthz' || pathname === '/readyz' || pathname.startsWith('/api/v1/');
|
||||
}
|
||||
@@ -114,6 +126,7 @@ async function proxyRequest(
|
||||
response: ServerResponse,
|
||||
upstreamHost: string,
|
||||
upstreamPort: number,
|
||||
gatewayToken: string | undefined,
|
||||
): Promise<void> {
|
||||
await new Promise<void>((resolvePromise) => {
|
||||
const upstream = httpRequest(
|
||||
@@ -122,7 +135,7 @@ async function proxyRequest(
|
||||
port: upstreamPort,
|
||||
method: incoming.method,
|
||||
path: incoming.url,
|
||||
headers: withoutHopByHop(incoming.headers),
|
||||
headers: trustedUpstreamHeaders(incoming.headers, gatewayToken),
|
||||
},
|
||||
(upstreamResponse) => {
|
||||
response.writeHead(
|
||||
@@ -235,7 +248,7 @@ export function createCanaryGateway(options: CanaryGatewayOptions): CanaryGatewa
|
||||
}
|
||||
|
||||
if (isProxyPath(pathname)) {
|
||||
await proxyRequest(request, response, upstreamHost, upstreamPort);
|
||||
await proxyRequest(request, response, upstreamHost, upstreamPort, options.gatewayToken);
|
||||
return;
|
||||
}
|
||||
if (pathname.startsWith('/api')) return sendText(response, 404, 'Not Found');
|
||||
@@ -245,7 +258,11 @@ export function createCanaryGateway(options: CanaryGatewayOptions): CanaryGatewa
|
||||
|
||||
const distRoot = await realpath(resolve(options.distDir)).catch(() => resolve(options.distDir));
|
||||
if (pathname !== '/' && (await serveFile(request, response, distRoot, pathname))) return;
|
||||
if (!(await serveFile(request, response, distRoot, '/index.html'))) {
|
||||
if (
|
||||
pathname.startsWith('/assets/') ||
|
||||
extname(pathname) !== '' ||
|
||||
!(await serveFile(request, response, distRoot, '/index.html'))
|
||||
) {
|
||||
sendText(response, 404, 'Not Found');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user