fix(undiciRequest): file uploading (#11320)

* fix(undiciRequest): file uploading

* fix: different approach

* fix: revert to the previous approach

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Almeida
2025-12-03 14:40:15 +00:00
committed by GitHub
parent 633fdd8f28
commit 0aaba0305f
6 changed files with 19 additions and 1 deletions

View File

@@ -24,6 +24,7 @@ beforeEach(() => {
setGlobalDispatcher(mockAgent); // enabled the mock client to intercept requests setGlobalDispatcher(mockAgent); // enabled the mock client to intercept requests
mockPool = mockAgent.get('https://discord.com'); mockPool = mockAgent.get('https://discord.com');
api.setAgent(mockAgent);
}); });
afterEach(async () => { afterEach(async () => {

View File

@@ -37,6 +37,8 @@ beforeEach(() => {
setGlobalDispatcher(mockAgent); // enabled the mock client to intercept requests setGlobalDispatcher(mockAgent); // enabled the mock client to intercept requests
mockPool = mockAgent.get('https://discord.com'); mockPool = mockAgent.get('https://discord.com');
api.setAgent(mockAgent);
fetchApi.setAgent(mockAgent);
}); });
afterEach(async () => { afterEach(async () => {

View File

@@ -481,6 +481,8 @@ test('perm server outage', async () => {
test('server responding too slow', async () => { test('server responding too slow', async () => {
const api2 = new REST({ timeout: 1 }).setToken('A-Very-Really-Real-Token'); const api2 = new REST({ timeout: 1 }).setToken('A-Very-Really-Real-Token');
api2.setAgent(mockAgent);
mockPool mockPool
.intercept({ .intercept({
path: genPath('/slow'), path: genPath('/slow'),

View File

@@ -15,6 +15,7 @@ beforeEach(() => {
setGlobalDispatcher(mockAgent); setGlobalDispatcher(mockAgent);
mockPool = mockAgent.get('https://discord.com'); mockPool = mockAgent.get('https://discord.com');
api.setAgent(mockAgent);
}); });
afterEach(async () => { afterEach(async () => {

View File

@@ -28,6 +28,7 @@ beforeEach(() => {
setGlobalDispatcher(mockAgent); // enabled the mock client to intercept requests setGlobalDispatcher(mockAgent); // enabled the mock client to intercept requests
mockPool = mockAgent.get('https://discord.com'); mockPool = mockAgent.get('https://discord.com');
api.setAgent(mockAgent);
}); });
afterEach(async () => { afterEach(async () => {

View File

@@ -1,12 +1,14 @@
import { STATUS_CODES } from 'node:http'; import { STATUS_CODES } from 'node:http';
import { URLSearchParams } from 'node:url'; import { URLSearchParams } from 'node:url';
import { types } from 'node:util'; import { types } from 'node:util';
import { type RequestInit, request, Headers, FormData as UndiciFormData } from 'undici'; import { type RequestInit, request, Headers, FormData as UndiciFormData, Agent } from 'undici';
import type { HeaderRecord } from 'undici/types/header.js'; import type { HeaderRecord } from 'undici/types/header.js';
import type { ResponseLike } from '../shared.js'; import type { ResponseLike } from '../shared.js';
export type RequestOptions = Exclude<Parameters<typeof request>[1], undefined>; export type RequestOptions = Exclude<Parameters<typeof request>[1], undefined>;
let localAgent: Agent | null = null;
export async function makeRequest(url: string, init: RequestInit): Promise<ResponseLike> { export async function makeRequest(url: string, init: RequestInit): Promise<ResponseLike> {
// The cast is necessary because `headers` and `method` are narrower types in `undici.request` // The cast is necessary because `headers` and `method` are narrower types in `undici.request`
// our request path guarantees they are of acceptable type for `undici.request` // our request path guarantees they are of acceptable type for `undici.request`
@@ -14,6 +16,15 @@ export async function makeRequest(url: string, init: RequestInit): Promise<Respo
...init, ...init,
body: await resolveBody(init.body), body: await resolveBody(init.body),
} as RequestOptions; } as RequestOptions;
// Mismatched dispatchers from the Node.js-bundled undici and package-installed undici breaks file uploads.
// So we ensure that we always pass an Agent to request()
// https://github.com/nodejs/node/issues/59012
if (!options.dispatcher) {
localAgent ??= new Agent();
options.dispatcher = localAgent;
}
const res = await request(url, options); const res = await request(url, options);
return { return {
body: res.body, body: res.body,