diff --git a/README.md b/README.md index 17b2ab32f..ce321cf52 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ the passed options and sends the request using [fetch](https://developer.mozilla - [Special cases](#special-cases) - [The `data` parameter – set request body directly](#the-data-parameter--set-request-body-directly) - [Set parameters for both the URL/query and the request body](#set-parameters-for-both-the-urlquery-and-the-request-body) + - [Set a custom Agent to your requests](#set-a-custom-agent-to-your-requests) - [LICENSE](#license) @@ -345,6 +346,17 @@ const { data: app } = await requestWithAuth( Used for internal logging. Defaults to console. + + + options.request.parseSuccessResponseBody + + + boolean + + + If set to false the returned `response` will be passed through from `fetch`. This is useful to stream response.body when downloading files from the GitHub API. + + All other options except `options.request.*` will be passed depending on the `method` and `url` options. @@ -528,6 +540,40 @@ request( ); ``` +### Set a custom Agent to your requests + +The way to pass a custom `Agent` to requests is by creating a custom `fetch` function and pass it as `options.request.fetch`. A good example can be [undici's `fetch` implementation](https://undici.nodejs.org/#/?id=undicifetchinput-init-promise). + +Example ([See example in CodeSandbox](https://codesandbox.io/p/sandbox/nifty-stitch-wdlwlf)) + +```js +import { request } from "@octokit/request"; +import { fetch as undiciFetch, Agent } from "undici"; + +/** @type {typeof import("undici").fetch} */ +const myFetch = (url, options) => { + return undiciFetch(url, { + ...options, + dispatcher: new Agent({ + keepAliveTimeout: 10, + keepAliveMaxTimeout: 10, + }), + }); +}; + +const { data } = await request("GET /users/{username}", { + username: "octocat", + headers: { + "X-GitHub-Api-Version": "2022-11-28", + }, + options: { + request: { + fetch: myFetch, + }, + }, +}); +``` + ## LICENSE [MIT](LICENSE) diff --git a/package-lock.json b/package-lock.json index 58c8e0223..8e0dca4c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@octokit/endpoint": "^9.0.0", "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", + "@octokit/types": "^11.1.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, @@ -2013,9 +2013,9 @@ "dev": true }, "node_modules/@octokit/types": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.0.0.tgz", - "integrity": "sha512-h4iyfMpQUdub1itwTn6y7z2a3EtPuer1paKfsIbZErv0LBbZYGq6haiPUPJys/LetPqgcX3ft33O16XuS03Anw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", "dependencies": { "@octokit/openapi-types": "^18.0.0" } diff --git a/package.json b/package.json index 509113dc1..8c43062cd 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dependencies": { "@octokit/endpoint": "^9.0.0", "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", + "@octokit/types": "^11.1.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, diff --git a/src/fetch-wrapper.ts b/src/fetch-wrapper.ts index 0a4f40942..0e6987176 100644 --- a/src/fetch-wrapper.ts +++ b/src/fetch-wrapper.ts @@ -11,6 +11,8 @@ export default function fetchWrapper( requestOptions.request && requestOptions.request.log ? requestOptions.request.log : console; + const parseSuccessResponseBody = + requestOptions.request?.parseSuccessResponseBody !== false; if ( isPlainObject(requestOptions.body) || @@ -113,7 +115,9 @@ export default function fetchWrapper( throw error; } - return getResponseData(response); + return parseSuccessResponseBody + ? await getResponseData(response) + : response.body; }) .then((data) => { return { diff --git a/test/request.test.ts b/test/request.test.ts index 59263941b..86e79bbdb 100644 --- a/test/request.test.ts +++ b/test/request.test.ts @@ -1,5 +1,5 @@ import fs from "fs"; -import stream from "stream"; +import stream, { Stream } from "stream"; import { getUserAgent } from "universal-user-agent"; import fetchMock from "fetch-mock"; @@ -1021,4 +1021,35 @@ x//0u+zd/R/QRUzLOw4N72/Hu+UG6MNt5iDZFCtapRaKt6OvSBwy8w== expect(error.name).toEqual("AbortError"); }); }); + + it("request should pass the stream in the response", () => { + const mock = fetchMock.sandbox().get( + "https://api.github.com/repos/octokit-fixture-org/release-assets/tarball/main", + { + status: 200, + headers: { + "content-type": "application/x-gzip", + }, + body: fs.createReadStream(__filename), + }, + { + sendAsJson: false, + }, + ); + + return request("GET /repos/{owner}/{repo}/tarball/{branch}", { + owner: "octokit-fixture-org", + repo: "release-assets", + branch: "main", + request: { + parseSuccessResponseBody: false, + fetch: mock, + }, + }).then((response) => { + expect(response.status).toEqual(200); + expect(response.headers["content-type"]).toEqual("application/x-gzip"); + expect(response.data).toBeInstanceOf(Stream); + expect(mock.done()).toBe(true); + }); + }); });