Skip to content

Commit

Permalink
feat(fetch-http-handler): add customization option for requestInit (#…
Browse files Browse the repository at this point in the history
…1397)

* feat(fetch-http-handler): add customization option for requestInit

* comment wording
  • Loading branch information
kuhe authored Sep 12, 2024
1 parent 918c402 commit cf9257e
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .changeset/dull-tomatoes-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@smithy/fetch-http-handler": patch
"@smithy/types": patch
---

add requestInit options to fetch
72 changes: 72 additions & 0 deletions packages/fetch-http-handler/src/fetch-http-handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ let timeoutSpy: jest.SpyInstance<any>;

(global as any).Request = mockRequest;
(global as any).Headers = jest.fn();
const globalFetch = global.fetch;

describe(FetchHttpHandler.name, () => {
beforeEach(() => {
Expand All @@ -23,6 +24,10 @@ describe(FetchHttpHandler.name, () => {
}
});

afterAll(() => {
global.fetch = globalFetch;
});

it("makes requests using fetch", async () => {
const mockResponse = {
headers: {
Expand Down Expand Up @@ -454,6 +459,73 @@ describe(FetchHttpHandler.name, () => {
});
});

describe("custom requestInit", () => {
it("should allow setting cache requestInit", async () => {
const mockResponse = {
headers: {
entries() {
return [];
},
},
blob: jest.fn().mockResolvedValue(new Blob()),
};
const mockFetch = jest.fn().mockResolvedValue(mockResponse);
(global as any).fetch = mockFetch;

const fetchHttpHandler = new FetchHttpHandler({
cache: "no-store",
});

await fetchHttpHandler.handle({} as any, {});

expect(mockRequest.mock.calls[0][1].cache).toBe("no-store");
});

it("should allow setting custom requestInit", async () => {
const mockResponse = {
headers: {
entries() {
return [];
},
},
blob: jest.fn().mockResolvedValue(new Blob()),
};
const mockFetch = jest.fn().mockResolvedValue(mockResponse);
(global as any).fetch = mockFetch;

const fetchHttpHandler = new FetchHttpHandler({
requestInit(req) {
return {
referrer: "me",
cache: "reload",
headers: {
a: "a",
b: req.headers.b,
},
};
},
});

await fetchHttpHandler.handle(
{
headers: {
b: "b",
},
} as any,
{}
);

expect(mockRequest.mock.calls[0][1]).toEqual({
referrer: "me",
cache: "reload",
headers: {
a: "a",
b: "b",
},
});
});
});

// The Blob implementation does not implement Blob.text, so we deal with it here.
async function blobToText(blob: Blob): Promise<string> {
const reader = new FileReader();
Expand Down
6 changes: 6 additions & 0 deletions packages/fetch-http-handler/src/fetch-http-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ export class FetchHttpHandler implements HttpHandler<FetchHttpHandlerConfig> {
headers: new Headers(request.headers),
method: method,
credentials,
cache: this.config!.cache ?? "default",
};

if (body) {
requestOptions.duplex = "half";
}
Expand All @@ -127,6 +129,10 @@ export class FetchHttpHandler implements HttpHandler<FetchHttpHandlerConfig> {
requestOptions.keepalive = keepAlive;
}

if (typeof this.config.requestInit === "function") {
Object.assign(requestOptions, this.config.requestInit(request));
}

let removeSignalEventListener = () => {};

const fetchRequest = new Request(url, requestOptions);
Expand Down
27 changes: 27 additions & 0 deletions packages/types/src/http/httpHandlerInitialization.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Agent as hAgent, AgentOptions as hAgentOptions } from "http";
import type { Agent as hsAgent, AgentOptions as hsAgentOptions } from "https";

import { HttpRequest as IHttpRequest } from "../http";
import { Logger } from "../logger";

/**
Expand Down Expand Up @@ -97,4 +98,30 @@ export interface FetchHttpHandlerOptions {
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
*/
credentials?: "include" | "omit" | "same-origin" | undefined | string;

/**
* Cache settings for fetch.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request/cache
*/
cache?: "default" | "force-cache" | "no-cache" | "no-store" | "only-if-cached" | "reload";

/**
* An optional function that produces additional RequestInit
* parameters for each httpRequest.
*
* This is applied last via merging with Object.assign() and overwrites other values
* set from other sources.
*
* @example
* ```js
* new Client({
* requestHandler: {
* requestInit(httpRequest) {
* return { cache: "no-store" };
* }
* }
* });
* ```
*/
requestInit?: (httpRequest: IHttpRequest) => RequestInit;
}

0 comments on commit cf9257e

Please sign in to comment.