Skip to content

Commit 633e375

Browse files
feat: support application/octet-stream request bodies (#892)
1 parent f932adc commit 633e375

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

src/core.ts

+27-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
type HeadersInit,
2020
} from './_shims/index';
2121
export { type Response };
22-
import { isMultipartBody } from './uploads';
22+
import { BlobLike, isBlobLike, isMultipartBody } from './uploads';
2323
export {
2424
maybeMultipartFormRequestOptions,
2525
multipartFormRequestOptions,
@@ -249,7 +249,17 @@ export abstract class APIClient {
249249
path: string,
250250
opts?: PromiseOrValue<RequestOptions<Req>>,
251251
): APIPromise<Rsp> {
252-
return this.request(Promise.resolve(opts).then((opts) => ({ method, path, ...opts })));
252+
return this.request(
253+
Promise.resolve(opts).then(async (opts) => {
254+
const body =
255+
opts && isBlobLike(opts?.body) ? new DataView(await opts.body.arrayBuffer())
256+
: opts?.body instanceof DataView ? opts.body
257+
: opts?.body instanceof ArrayBuffer ? new DataView(opts.body)
258+
: opts && ArrayBuffer.isView(opts?.body) ? new DataView(opts.body.buffer)
259+
: opts?.body;
260+
return { method, path, ...opts, body };
261+
}),
262+
);
253263
}
254264

255265
getAPIList<Item, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(
@@ -271,6 +281,8 @@ export abstract class APIClient {
271281
const encoded = encoder.encode(body);
272282
return encoded.length.toString();
273283
}
284+
} else if (ArrayBuffer.isView(body)) {
285+
return body.byteLength.toString();
274286
}
275287

276288
return null;
@@ -280,7 +292,9 @@ export abstract class APIClient {
280292
const { method, path, query, headers: headers = {} } = options;
281293

282294
const body =
283-
isMultipartBody(options.body) ? options.body.body
295+
ArrayBuffer.isView(options.body) || (options.__binaryRequest && typeof options.body === 'string') ?
296+
options.body
297+
: isMultipartBody(options.body) ? options.body.body
284298
: options.body ? JSON.stringify(options.body, null, 2)
285299
: null;
286300
const contentLength = this.calculateContentLength(body);
@@ -735,7 +749,9 @@ export type Headers = Record<string, string | null | undefined>;
735749
export type DefaultQuery = Record<string, string | undefined>;
736750
export type KeysEnum<T> = { [P in keyof Required<T>]: true };
737751

738-
export type RequestOptions<Req = unknown | Record<string, unknown> | Readable> = {
752+
export type RequestOptions<
753+
Req = unknown | Record<string, unknown> | Readable | BlobLike | ArrayBufferView | ArrayBuffer,
754+
> = {
739755
method?: HTTPMethod;
740756
path?: string;
741757
query?: Req | undefined;
@@ -749,6 +765,7 @@ export type RequestOptions<Req = unknown | Record<string, unknown> | Readable> =
749765
signal?: AbortSignal | undefined | null;
750766
idempotencyKey?: string;
751767

768+
__binaryRequest?: boolean | undefined;
752769
__binaryResponse?: boolean | undefined;
753770
__streamClass?: typeof Stream;
754771
};
@@ -770,6 +787,7 @@ const requestOptionsKeys: KeysEnum<RequestOptions> = {
770787
signal: true,
771788
idempotencyKey: true,
772789

790+
__binaryRequest: true,
773791
__binaryResponse: true,
774792
__streamClass: true,
775793
};
@@ -783,10 +801,11 @@ export const isRequestOptions = (obj: unknown): obj is RequestOptions => {
783801
);
784802
};
785803

786-
export type FinalRequestOptions<Req = unknown | Record<string, unknown> | Readable> = RequestOptions<Req> & {
787-
method: HTTPMethod;
788-
path: string;
789-
};
804+
export type FinalRequestOptions<Req = unknown | Record<string, unknown> | Readable | DataView> =
805+
RequestOptions<Req> & {
806+
method: HTTPMethod;
807+
path: string;
808+
};
790809

791810
declare const Deno: any;
792811
declare const EdgeRuntime: any;

0 commit comments

Comments
 (0)