handleRelayRequest function

Future<void> handleRelayRequest(
  1. HttpRequest request, {
  2. required String? requireCredential(),
  3. required String? origin,
  4. bool allowAnyHost = false,
})

One POST /relay call (issue #633): the desktop add-in taskpane has no extension to carry its provider HTTP, so the pane proxies it through the local hub, which fetches CORS-free by construction. The body is the SW-bridge request envelope {url, method?, headers?, bodyB64?}; the upstream answer is streamed back raw (status + content-type + body), so provider SSE flows through incrementally.

Authentication (issue #792): /relay demands a bearer credential on EVERY scope — the master secret when the hub is protected, else the ephemeral per-serve LocalHub.relaySecret. A null credential (the hub never started) authenticates nothing: fail closed, 401 everything. A present but non-allowlisted Origin is a 403 REJECTION before any upstream work — the old behavior answered minus CORS headers, which still executed the fetch for the hostile page's benefit.

Implementation

Future<void> handleRelayRequest(
  HttpRequest request, {
  required String? Function() requireCredential,
  required String? origin,
  bool allowAnyHost = false,
}) async {
  final allowedOrigin = relayAllowedOrigin(origin);
  if (request.method == 'OPTIONS') {
    await _relayPreflight(request, allowedOrigin);
    return;
  }
  final credential = requireCredential();
  if (credential == null ||
      credential.isEmpty ||
      request.headers.value('authorization') != 'Bearer $credential') {
    // Keep-alive pools must not reuse a rejected socket (same shape as
    // the rejected WS upgrade — a stale pooled connection surfaces as
    // "connection closed" on the client's NEXT request).
    request.response.headers.set(HttpHeaders.connectionHeader, 'close');
    _relayMarkRejection(request);
    request.response.statusCode = 401;
    await request.response.close();
    return;
  }
  if (origin != null && allowedOrigin == null) {
    request.response.headers.set(HttpHeaders.connectionHeader, 'close');
    _relayMarkRejection(request);
    request.response.statusCode = 403;
    request.response.write('{"error":"origin not allowed"}');
    await request.response.close();
    return;
  }
  final parsed = await _relayEnvelope(request, allowedOrigin);
  if (parsed == null) return;
  if (!relayDestinationAllowed(parsed.$1, allowAnyHost: allowAnyHost)) {
    request.response.headers.set(HttpHeaders.connectionHeader, 'close');
    _relayMarkRejection(request);
    request.response.statusCode = 403;
    _relayCors(request, allowedOrigin);
    request.response.write('{"error":"destination not allowed"}');
    await request.response.close();
    return;
  }
  await _relayForward(
    request,
    parsed.$1,
    parsed.$2,
    allowedOrigin,
    allowAnyHost: allowAnyHost,
  );
}