undici
undici copied to clipboard
DispatchInterceptor with POST request doesn't work
Bug Description
When a POST request is made using a dispatch interceptor and undici.DecoratorHandler, an error is thrown if the request includes a body. However, if the request does not include a body, no error is thrown.
/Users/battal/Desktop/files/projects/win-bot/node_modules/undici/index.js:109
Error.captureStackTrace(err, this)
^
TypeError: fetch failed
at fetch (/Users/battal/Desktop/files/projects/win-bot/node_modules/undici/index.js:109:13) {
cause: TypeError: this.handler.onBodySent is not a function
at undiciInterceptorTesto.onBodySent (/Users/battal/Desktop/files/projects/win-bot/node_modules/undici/lib/handler/DecoratorHandler.js:33:25)
at Request.onBodySent (/Users/battal/Desktop/files/projects/win-bot/node_modules/undici/lib/core/request.js:205:24)
at AsyncWriter.write (/Users/battal/Desktop/files/projects/win-bot/node_modules/undici/lib/client.js:1714:13)
at writeIterable (/Users/battal/Desktop/files/projects/win-bot/node_modules/undici/lib/client.js:1637:19)
}
Reproducible By
import * as undici from "undici";
import { fetch } from "undici";
const undiciInterceptorHeaders = (dispatch: any) => {
class undiciInterceptorTesto extends undici.DecoratorHandler {
onHeaders(statusCode: any, headers: any, resume: any) {
// @ts-ignore
return super.onHeaders(statusCode, headers, resume);
}
}
return function InterceptedDispatch(opts: any, handler: any) {
return dispatch(opts, new undiciInterceptorTesto(handler));
};
};
let dispatcher = new undici.Agent({
interceptors: {
Client: [undiciInterceptorHeaders as unknown as undici.Dispatcher],
},
});
fetch("https://postman-echo.com/post", {
method: "POST",
body: new URLSearchParams("amk=5&asdm=6"),
// body: new URLSearchParams(""), // works fine
dispatcher,
})
.then((res) => res.json())
.then((body) => {
console.log(body);
});
Expected Behavior
it should not throw error
Environment
Macos Sonoma Beta 4 Node v20.5.0
after some fiddling, creating a empty onBodySent method on undici.DecoratorHandler makes things work, not sure why.
const undiciInterceptorHeaders = (dispatch: any) => {
class undiciInterceptorTesto extends undici.DecoratorHandler {
onHeaders(statusCode: any, headers: any, resume: any) {
// @ts-ignore
return super.onHeaders(statusCode, headers, resume);
}
onBodySent() {} // <---- here
}
return function InterceptedDispatch(opts: any, handler: any) {
return dispatch(opts, new undiciInterceptorTesto(handler));
};
};
looks like on request.js:201, even tho "this[kHandler]" doesnt have a onBodySent function, code sees it like there is one, black magic to me how this happens
onBodySent (chunk) {
if (this[kHandler].onBodySent) {
// i edited this line
console.log(this[kHandler], this[kHandler].onBodySent)
try {
this[kHandler].onBodySent(chunk)
} catch (err) {
this.onError(err)
}
}
}
undiciInterceptorTesto {
handler: {
body: null,
abort: [Function (anonymous)],
onConnect: [Function: onConnect],
onHeaders: [Function: onHeaders],
onData: [Function: onData],
onComplete: [Function: onComplete],
onError: [Function: onError],
onUpgrade: [Function: onUpgrade]
}
} [Function: onBodySent]
https://github.com/nodejs/undici/blob/c83b084879fa0bb8e0469d31ec61428ac68160d5/docs/api/Dispatcher.md?plain=1#L214
it would appear as though either the docs are wrong or the code should work without an onBodySent, not entirely sure which is more correct.