MCPcopy Index your code
hub / github.com/garrytan/gstack / handleLoopback

Function handleLoopback

ios-qa/daemon/src/index.ts:230–280  ·  view source on GitHub ↗

* Loopback handler — full surface for the spawning agent. No auth (the * loopback bind itself is the boundary).

(ctx: HandlerCtx)

Source from the content-addressed store, hash-verified

228 * loopback bind itself is the boundary).
229 */
230async function handleLoopback(ctx: HandlerCtx): Promise<void> {
231 const { req, res, tokenStore, getTunnel } = ctx;
232 const url = parseUrl(req.url ?? '/');
233 const path = url.pathname ?? '/';
234 const method = req.method ?? 'GET';
235
236 try {
237 // /healthz — public on loopback.
238 if (method === 'GET' && path === '/healthz') {
239 sendJson(res, 200, { version: '1.0.0', mode: 'loopback' });
240 return;
241 }
242
243 // /auth/sessions — list active sessions (owner only).
244 if (method === 'GET' && path === '/auth/sessions') {
245 sendJson(res, 200, { sessions: tokenStore.list() });
246 return;
247 }
248
249 // /auth/revoke — revoke a token.
250 if (method === 'POST' && path === '/auth/revoke') {
251 const body = await readBody(req);
252 if ('error' in body) { sendJson(res, 413, body); return; }
253 const parsed = JSON.parse(body.toString('utf-8') || '{}') as { token?: string; identity?: string };
254 let count = 0;
255 if (parsed.token) {
256 count = tokenStore.revoke(parsed.token) ? 1 : 0;
257 } else if (parsed.identity) {
258 count = tokenStore.revokeByIdentity(parsed.identity);
259 }
260 sendJson(res, 200, { revoked: count });
261 return;
262 }
263
264 // Other endpoints — proxy to the device.
265 const tunnel = await getTunnel();
266 if (!tunnel) {
267 sendJson(res, 503, { error: 'device_not_connected' });
268 return;
269 }
270 const body = await readBody(req);
271 if ('error' in body) { sendJson(res, 413, body); return; }
272 const sessionId = (req.headers['x-session-id'] as string | undefined) ?? null;
273 const agentIdentity = (req.headers['x-agent-identity'] as string | undefined) ?? undefined;
274 const upstream = await proxyToDevice({ inbound: req, body, tunnel, sessionId, agentIdentity });
275 res.writeHead(upstream.status, upstream.headers);
276 res.end(upstream.body);
277 } catch (err) {
278 sendJson(res, 500, { error: 'internal_error', detail: (err as Error).message });
279 }
280}
281
282interface TailnetCtx extends HandlerCtx {
283 whoIsImpl: (addr: string) => Promise<{ identity: string; raw: unknown }>;

Callers 1

startDaemonFunction · 0.85

Calls 8

proxyToDeviceFunction · 0.90
sendJsonFunction · 0.85
readBodyFunction · 0.85
getTunnelFunction · 0.85
listMethod · 0.80
revokeMethod · 0.80
revokeByIdentityMethod · 0.80
endMethod · 0.80

Tested by

no test coverage detected