mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-03 00:28:02 +02:00
v1.39.0.0 feat: buildFetchHandler factory unblocks gbrowser submodule consumption (#1511)
* feat: buildFetchHandler factory unblocks gbrowser submodule consumption
Add buildFetchHandler(cfg: ServerConfig): ServerHandle in browse/src/server.ts.
Refactor start() to delegate handler construction to the factory and read env
once via resolveConfigFromEnv(). Wire the beforeRoute hook (runs after the
tunnel surface filter, before per-route dispatch).
Auth is now cfg-driven end-to-end. Module-level AUTH_TOKEN const +
initRegistry(AUTH_TOKEN) boot call, validateAuth, and shutdown are deleted;
factory closure owns them. start() threads cfg.authToken into launchHeaded,
the state-file write, and the factory.
initRegistry is idempotent for same-token re-init; throws clearly for
different-token re-init. __resetRegistry() test helper added (mirrors
__resetConnectRateLimit). Existing tests that did rotateRoot() ->
initRegistry('fixed-token') swap to __resetRegistry() to avoid the new guard.
14 factory contract tests added covering ServerHandle shape, auth wiring,
validation throws, hook semantics across both surfaces, and registry
idempotency.
Source-pattern tests in dual-listener.test.ts and server-auth.test.ts
updated for the new identifiers (handle.fetchLocal/fetchTunnel, authToken,
shutdownFn).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* chore: bump version and changelog (v1.39.0.0)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -147,6 +147,16 @@ const tokens = new Map<string, TokenInfo>();
|
||||
let rootToken: string = '';
|
||||
|
||||
export function initRegistry(root: string): void {
|
||||
// Idempotent re-init: same token is a no-op so embedders can call this
|
||||
// alongside any prior call without fighting. Different token after init
|
||||
// means a misconfigured caller — throw clearly rather than silently
|
||||
// invalidate every scoped token already issued.
|
||||
if (rootToken !== '' && rootToken !== root) {
|
||||
throw new Error(
|
||||
'token-registry already initialized with a different token; ' +
|
||||
'embedders must call buildFetchHandler before any registry-mutating code path'
|
||||
);
|
||||
}
|
||||
rootToken = root;
|
||||
}
|
||||
|
||||
@@ -512,3 +522,13 @@ export function checkConnectRateLimit(): boolean {
|
||||
export function __resetConnectRateLimit(): void {
|
||||
connectAttempts = [];
|
||||
}
|
||||
|
||||
// Test-only reset. Zeroes the registry so a subsequent initRegistry call
|
||||
// always succeeds. Mirrors __resetConnectRateLimit. Needed by tests that
|
||||
// follow the rotateRoot() pattern — rotateRoot leaves rootToken non-empty,
|
||||
// which would otherwise trip the initRegistry mismatch guard.
|
||||
export function __resetRegistry(): void {
|
||||
rootToken = '';
|
||||
tokens.clear();
|
||||
rateBuckets.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user