From e343948ec3a8b1052f50f80b109692dfd545f4eb Mon Sep 17 00:00:00 2001 From: Khafra Date: Fri, 1 Mar 2024 03:43:14 -0500 Subject: [PATCH] doc deprecate bodymixin.formData (#2892) * doc deprecate bodymixin.formData * fixup * add dedicated body mixin section --- docs/README.md | 8 ++++++-- docs/docs/api/Fetch.md | 32 +++++++++++++++++++++++++++++++- types/fetch.d.ts | 41 ++++++++++++++++++++--------------------- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/docs/README.md b/docs/README.md index 144b4cb6534..84655d48cb0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -60,10 +60,14 @@ console.log('trailers', trailers) The `body` mixins are the most common way to format the request/response body. Mixins include: -- [`.formData()`](https://fetch.spec.whatwg.org/#dom-body-formdata) +- [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer) +- [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob) - [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json) - [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text) +> [!NOTE] +> The body returned from `undici.request` does not implement `.formData()`. + Example usage: ```js @@ -226,7 +230,7 @@ await fetch('https://example.com', { body: data, method: 'POST', duplex: 'half' - half -In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`. And fetch requests are currently always be full duplex. More detail refer to [Fetch Standard.](https://fetch.spec.whatwg.org/#dom-requestinit-duplex) +In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`, however, fetch requests are currently always full duplex. For more detail refer to the [Fetch Standard.](https://fetch.spec.whatwg.org/#dom-requestinit-duplex). #### `response.body` diff --git a/docs/docs/api/Fetch.md b/docs/docs/api/Fetch.md index b5a62422a24..5e480f5acfa 100644 --- a/docs/docs/api/Fetch.md +++ b/docs/docs/api/Fetch.md @@ -12,7 +12,9 @@ In Node versions v18.13.0 and above and v19.2.0 and above, undici will default t ## FormData -This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData) +This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData). + +If any parameters are passed to the FormData constructor other than `undefined`, an error will be thrown. Other parameters are ignored. ## Response @@ -25,3 +27,31 @@ This API is implemented as per the standard, you can find documentation on [MDN] ## Header This API is implemented as per the standard, you can find documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Headers) + +# Body Mixins + +`Response` and `Request` body inherit body mixin methods. These methods include: + +- [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer) +- [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob) +- [`.formData()`](https://fetch.spec.whatwg.org/#dom-body-formdata) +- [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json) +- [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text) + +There is an ongoing discussion regarding `.formData()` and its usefulness and performance in server environments. It is recommended to use a dedicated library for parsing `multipart/form-data` bodies, such as [Busboy](https://www.npmjs.com/package/busboy) or [@fastify/busboy](https://www.npmjs.com/package/@fastify/busboy). + +These libraries can be interfaced with fetch with the following example code: + +```mjs +import { Busboy } from '@fastify/busboy' +import { Readable } from 'node:stream' + +const response = await fetch('...') +const busboy = new Busboy({ + headers: { + 'content-type': response.headers.get('content-type') + } +}) + +Readable.fromWeb(response.body).pipe(busboy) +``` diff --git a/types/fetch.d.ts b/types/fetch.d.ts index 440f2b00397..68779da13ba 100644 --- a/types/fetch.d.ts +++ b/types/fetch.d.ts @@ -27,12 +27,29 @@ export type BodyInit = | null | string -export interface BodyMixin { +export class BodyMixin { readonly body: ReadableStream | null readonly bodyUsed: boolean readonly arrayBuffer: () => Promise readonly blob: () => Promise + /** + * @deprecated This method is not recommended for parsing multipart/form-data bodies in server environments. + * It is recommended to use a library such as [@fastify/busboy](https://www.npmjs.com/package/@fastify/busboy) as follows: + * + * @example + * ```js + * import { Busboy } from '@fastify/busboy' + * import { Readable } from 'node:stream' + * + * const response = await fetch('...') + * const busboy = new Busboy({ headers: { 'content-type': response.headers.get('content-type') } }) + * + * // handle events emitted from `busboy` + * + * Readable.fromWeb(response.body).pipe(busboy) + * ``` + */ readonly formData: () => Promise readonly json: () => Promise readonly text: () => Promise @@ -135,7 +152,7 @@ export type RequestRedirect = 'error' | 'follow' | 'manual' export type RequestDuplex = 'half' -export declare class Request implements BodyMixin { +export declare class Request extends BodyMixin { constructor (input: RequestInfo, init?: RequestInit) readonly cache: RequestCache @@ -153,15 +170,6 @@ export declare class Request implements BodyMixin { readonly signal: AbortSignal readonly duplex: RequestDuplex - readonly body: ReadableStream | null - readonly bodyUsed: boolean - - readonly arrayBuffer: () => Promise - readonly blob: () => Promise - readonly formData: () => Promise - readonly json: () => Promise - readonly text: () => Promise - readonly clone: () => Request } @@ -181,7 +189,7 @@ export type ResponseType = export type ResponseRedirectStatus = 301 | 302 | 303 | 307 | 308 -export declare class Response implements BodyMixin { +export declare class Response extends BodyMixin { constructor (body?: BodyInit, init?: ResponseInit) readonly headers: Headers @@ -192,15 +200,6 @@ export declare class Response implements BodyMixin { readonly url: string readonly redirected: boolean - readonly body: ReadableStream | null - readonly bodyUsed: boolean - - readonly arrayBuffer: () => Promise - readonly blob: () => Promise - readonly formData: () => Promise - readonly json: () => Promise - readonly text: () => Promise - readonly clone: () => Response static error (): Response