fix(relay): never forward a tunneled body that lost frames (#2822)
When the relay drops mid-request, the prompt_async body frames can be lost. The tunnel host forwarded the request to loopback as an empty/truncated chunked body, which the server rejects with a bare 400 (empty response body) — the mobile app's 'Failed to send message (400)'. Host now buffers request bodies (<512KB) and forwards the complete body only once StreamEnd arrives; larger bodies still stream live. A new hasBody flag on the request head lets the host detect a body that delivered zero frames and abort it as an ambiguous transport failure (which the client already retries) instead of forwarding an empty body. A 15s body-delivery deadline converts stalled tunnels into clean aborts.
This commit is contained in:
@@ -61,6 +61,11 @@ export interface TunnelHttpRequestPayload {
|
||||
path: string;
|
||||
query: string;
|
||||
headers: Record<string, string>;
|
||||
/** True when the client had a request body to send. The host uses this to
|
||||
* distinguish a genuine bodyless request from one whose body frames were lost
|
||||
* through the tunnel (which it must abort as an ambiguous transport failure
|
||||
* instead of forwarding an empty body the loopback server rejects with 400). */
|
||||
hasBody?: boolean;
|
||||
}
|
||||
|
||||
export interface TunnelHttpResponsePayload {
|
||||
|
||||
@@ -819,6 +819,7 @@ export const createRelayTunnelClient = (options: RelayTunnelClientOptions): Rela
|
||||
path: request.path,
|
||||
query: request.query,
|
||||
headers: request.headers,
|
||||
hasBody: request.body !== null,
|
||||
};
|
||||
channel.send(encodeTunnelFrame(TunnelFrameType.HttpRequest, streamId, encodeJsonPayload(head)));
|
||||
void (async () => {
|
||||
|
||||
Reference in New Issue
Block a user