handleRelayRequest function
- HttpRequest request, {
- required String? requireCredential(),
- required String? origin,
- 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,
);
}