SSE generated functions are not using the serialized body from `beforeRequest`
Description
For a normal request, the serialized body is used. This is because beforeRequest will generate the serialized body. Example generated method:
const request: Client['request'] = async (options) => {
// @ts-expect-error
const { opts, url } = await beforeRequest(options);
const requestInit: ReqInit = {
redirect: 'follow',
...opts,
body: opts.serializedBody,
};
But for SSE the generator will still call beforeRequest to get the serialized body, but it doesn't use the serialized body:
const makeSseFn =
(method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
headers: opts.headers as unknown as Record<string, string>,
method,
url,
});
};
This means that callers of this method have to JSON.stringify, or we have to update the generated method to use serialized body.
Reproducible example or configuration
No response
OpenAPI specification (optional)
No response
System information (optional)
No response
Which version are you on? This might be fixed in v0.82.0
I was on v0.81.1, I just upgraded to v0.82.0 (looks like it was released an hour ago?) and it works! Sorry, I should have included that in my issue.
Context
We’re on @hey-api/[email protected] and rely on beforeRequest to produce signed SSE requests. The generated fetch client ignores the serializedBody returned from beforeRequest, so the request body never reaches the underlying fetch.
Minimal repro
import { createClient } from '@hey-api/openapi-ts/fetch';
const client = createClient({
baseUrl: 'https://example.test',
beforeRequest: async (options) => {
// e.g., we serialize + HMAC-sign the SSE handshake body here
return {
...options,
serializedBody: JSON.stringify({ token: 'signed-payload' }),
headers: { ...options.headers, 'content-type': 'application/json' },
};
},
});
await client.sse('/stream', {
method: 'POST',
body: { token: 'unsigned' },
onMessage: () => {},
});
Expected: the POST request carries {"token":"signed-payload"} (the serializedBody from beforeRequest).
Actual: the outgoing request still sends {"token":"unsigned"} (the original body), because the generated SSE client overwrites the RequestInit body with serializedBody before beforeRequest runs, but never copies it back in afterward.
Local patch
We patched dist/clients/core/serverSentEvents.ts and dist/clients/fetch/client.ts to:
- separate
serializedBodyfrom the rest ofbeforeRequestoptions, - forward it into the
RequestInitwe pass tonew Request(url, init), and - reuse the existing
getValidRequestBodyhelper so other clients stay consistent.
Would you consider reopening this? Without it, any SSE flow that needs to rewrite/serialize the body in beforeRequest (for signing, encryption, etc.) is broken.