Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript RequestInit interface missing 'duplex' #1769

Open
jimchou-dev opened this issue Aug 18, 2023 · 12 comments
Open

TypeScript RequestInit interface missing 'duplex' #1769

jimchou-dev opened this issue Aug 18, 2023 · 12 comments
Labels

Comments

@jimchou-dev
Copy link

In WHATWG RequestInit has RequestDuplex duplex property but it's missing in node-fetch typescript API

export interface RequestInit {
/**
* A BodyInit object or null to set request's body.
*/
body?: BodyInit | null;
/**
* A Headers object, an object literal, or an array of two-item arrays to set request's headers.
*/
headers?: HeadersInit;
/**
* A string to set request's method.
*/
method?: string;
/**
* A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect.
*/
redirect?: RequestRedirect;
/**
* An AbortSignal to set request's signal.
*/
signal?: AbortSignal | null;
/**
* A string whose value is a same-origin URL, "about:client", or the empty string, to set request’s referrer.
*/
referrer?: string;
/**
* A referrer policy to set request’s referrerPolicy.
*/
referrerPolicy?: ReferrerPolicy;
// Node-fetch extensions to the whatwg/fetch spec
agent?: RequestOptions['agent'] | ((parsedUrl: URL) => RequestOptions['agent']);
compress?: boolean;
counter?: number;
follow?: number;
hostname?: string;
port?: number;
protocol?: string;
size?: number;
highWaterMark?: number;
insecureHTTPParser?: boolean;
}

Based on this https://fetch.spec.whatwg.org/#enumdef-requestduplex if fetch body is ReadableStream it requires the options duplex, want to check if duplex will be added to the RequestInit type in the new the near future, if not what is the process to contribute to adding a new type.

Screenshots
https://fetch.spec.whatwg.org/#request-class
image

@jimmywarting
Copy link
Collaborator

node-fetch do kind of already support streams before duplex became spec'ed
i'm guessing duplex is more complicated that just simply adding a property to RequestInit

"half" is the only valid value and it is for initiating a half-duplex fetch (i.e., the user agent sends the entire request before processing the response). "full" is reserved for future use, for initiating a full-duplex fetch (i.e., the user agent can process the response before sending the entire request). This member needs to be set when body is a ReadableStream object. See issue #1254 for defining "full".

I'm not sure it's worth the time and effort into trying to add it to node-fetch when undici / NodeJS already supports the duplex option.

@jimchou-dev
Copy link
Author

Thanks for the quick response. When specifying the body as Blob.stream() to get the ReadableStream, I'm getting this error:

Uncaught (in promise) RestError: Error sending request: Failed to execute 'fetch' on 'Window': The `duplex` member must be specified for a request with a streaming body

Not sure if I'm doing something wrong, but when adding the duplex: 'half' option in RequestInit (with // @ts-ignore to ignore linter), it will work fine.

Since we are using typescript, we would like to have the duplex property being part of the type, what would be the process for me to contribute to add this RequestDuplex to RequestInit?

@guest271314
Copy link

"half" is the only valid value and it is for initiating a half-duplex fetch (i.e., the user agent sends the entire request before processing the response). "full" is reserved for future use, for initiating a full-duplex fetch (i.e., the user agent can process the response before sending the entire request). This member needs to be set when body is a ReadableStream object. See issue #1254 for defining "full".

Technically "half" functions as "full" right now in Node.js and Deno's implementation of fetch(). We can create a TransformStream, upload the readable side, write to the writable side and read the response in parallel.

No browser implements full-duplex using fetch() over the network at large directly.

However, on Chromium-based browsers we can full-duplex stream between a ServiceWorker and a WindowClient or Client, e.g., type some lower case letters in the input field here https://plnkr.co/edit/2PQK21kZTZvZ2oVi?preview.

We can use a browser extension to use Deno or Node.js implementation, for the capability to full-duplex stream to and from the server fom arbitrary Web pages, see https://github.com/guest271314/native-messaging-deno/tree/fetch-duplex, and https://github.com/guest271314/native-messaging-nodejs/tree/full-duplex.

@narajaon
Copy link

narajaon commented Oct 13, 2023

Hello, I encountered the same issue.
What would be the workaround if you guys don't want to implement this type ?

@alexblack
Copy link

Seems like an issue... node fetch RequestInit has a property duplex but Typescript doesn't recognize it, missing from the types?

@PassionPenguin
Copy link

PassionPenguin commented Dec 2, 2023

TypeScript requires me to add the missing duplex property when using fetch and PUT, but after added, it pops up, notifying me that duplex does not exist on RequestInit...

no duplex throws error on the fly:

TypeError: RequestInit: duplex option is required when sending a body.
    at new Request (node:internal/deps/undici/undici:5499:19)
    at R (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:340580)
    at D (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:60308)
    at /Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:62407
    at /Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/server/lib/trace/tracer.js:131:36
    at NoopContextManager.with (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:7062)
    at ContextAPI.with (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:518)
    at NoopTracer.startActiveSpan (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:18093)
    at ProxyTracer.startActiveSpan (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:18854)
    at /Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/server/lib/trace/tracer.js:120:103
    at NoopContextManager.with (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:7062)
    at ContextAPI.with (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/@opentelemetry/api/index.js:1:518)
    at NextTracerImpl.trace (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/server/lib/trace/tracer.js:120:28)
    at globalThis.fetch (/Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:56863)
    at MSGraphDriveProvider.uploadDriveItem (webpack-internal:///(rsc)/./src/lib/ms-graph/drive.ts:55:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async PUT (webpack-internal:///(rsc)/./src/app/api/graph/upload/route.tsx:30:22)
    at async /Users/hoarfroster/Desktop/hfrecipe/node_modules/next/dist/compiled/next-server/app-route.runtime.dev.js:6:62609

having duplex throws error on npm run build, but works directly on npm run dev

Type error: No overload matches this call.
  Overload 1 of 2, '(input: string | URL | Request, init?: RequestInit): Promise<Response>', gave the following error.
    Object literal may only specify known properties, and 'duplex' does not exist in type 'RequestInit'.
  Overload 2 of 2, '(input: URL | RequestInfo, init?: RequestInit): Promise<Response>', gave the following error.
    Object literal may only specify known properties, and 'duplex' does not exist in type 'RequestInit'.

  89 |                 },
  90 |                 body: content,
> 91 |                 duplex: 'half'
     |                 ^
  92 |             }
  93 |         ).then(async (res) => {
  94 |             return (await res.json()) as MSGraphDriveItem | MSGraphError;

@Jet315
Copy link

Jet315 commented Feb 10, 2024

Also getting this error. Does anyone have a resolution?

@ebox86
Copy link

ebox86 commented Feb 17, 2024

same issue, any update?

@agillespie-sp
Copy link

agillespie-sp commented Feb 29, 2024

Posting the fix for my use case ... which was an API proxy using NextJS (but it may help others into looking into what they're sending in the body of the fetch call).

The body in this case was a ReabableStream, to avoid the error or the above TypeScript issue we were able to resolve the stream with:

const body = await request.json();

then pass this as the body in the fetch call

@guest271314
Copy link

@agillespie-sp That's not streaming. We should be able to upload a ReadableStream as body using Request() and fetch().

@agillespie-sp
Copy link

passing the stream works, but only if you add duplex: "half" to the RequestInit object. Then you get into of the issue of duplex not being on the interface and potential build issues

@fzn0x
Copy link

fzn0x commented May 8, 2024

Is there any way to solve this instead of using // @ts-expect-error for TypeScript?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants