(req: IncomingMessage, res: ServerResponse)
| 6463 | } |
| 6464 | |
| 6465 | async function handleWorkspace(req: IncomingMessage, res: ServerResponse): Promise<void> { |
| 6466 | if (!isLoopbackAddress(req.socket.remoteAddress)) { |
| 6467 | errorResponse(res, 403, 'urn:ok:error:loopback-required', 'Loopback required.', { |
| 6468 | handler: 'workspace', |
| 6469 | }); |
| 6470 | return; |
| 6471 | } |
| 6472 | if (!isAllowedWorkspaceHostHeader(req.headers.host)) { |
| 6473 | errorResponse(res, 403, 'urn:ok:error:host-not-allowed', 'Host header not allowed.', { |
| 6474 | handler: 'workspace', |
| 6475 | }); |
| 6476 | return; |
| 6477 | } |
| 6478 | if (req.method !== 'GET') { |
| 6479 | errorResponse(res, 405, 'urn:ok:error:method-not-allowed', 'Method not allowed.', { |
| 6480 | handler: 'workspace', |
| 6481 | extraHeaders: { Allow: 'GET' }, |
| 6482 | }); |
| 6483 | return; |
| 6484 | } |
| 6485 | const resolvedRoot = resolve(contentDir); |
| 6486 | let resolvedContentDir = resolvedRoot; |
| 6487 | let symlinkResolved = true; |
| 6488 | try { |
| 6489 | resolvedContentDir = realpathSync(resolvedRoot); |
| 6490 | } catch (err) { |
| 6491 | const code = (err as NodeJS.ErrnoException | undefined)?.code; |
| 6492 | if (code === 'ENOENT') { |
| 6493 | console.warn('[workspace] contentDir does not exist; returning unresolved path', { |
| 6494 | path: resolvedRoot, |
| 6495 | }); |
| 6496 | symlinkResolved = false; |
| 6497 | } else { |
| 6498 | console.warn('[workspace] realpath failed for contentDir', { path: resolvedRoot, err }); |
| 6499 | errorResponse( |
| 6500 | res, |
| 6501 | 500, |
| 6502 | 'urn:ok:error:internal-server-error', |
| 6503 | 'Workspace realpath failed.', |
| 6504 | { handler: 'workspace', detail: code ?? undefined, cause: err }, |
| 6505 | ); |
| 6506 | return; |
| 6507 | } |
| 6508 | } |
| 6509 | successResponse( |
| 6510 | res, |
| 6511 | 200, |
| 6512 | WorkspaceSuccessSchema, |
| 6513 | { |
| 6514 | contentDir: resolvedContentDir, |
| 6515 | pathSeparator: sep, |
| 6516 | symlinkResolved, |
| 6517 | }, |
| 6518 | { handler: 'workspace' }, |
| 6519 | ); |
| 6520 | } |
| 6521 | |
| 6522 | const handleAsset = withValidation( |
nothing calls this directly
no test coverage detected