{"id":52037649,"url":"https://github.com/adobe/fetch","last_synced_at":"2026-08-01T21:03:09.246Z","repository":{"id":38020929,"uuid":"223983348","full_name":"adobe/fetch","owner":"adobe","description":"Simplified HTTP/1(.1) and HTTP/2 requests with Server Push Support","archived":false,"fork":false,"pushed_at":"2026-06-23T09:00:49.000Z","size":3590,"stargazers_count":60,"open_issues_count":1,"forks_count":14,"subscribers_count":35,"default_branch":"main","last_synced_at":"2026-06-23T12:04:42.746Z","etag":null,"topics":["cache","fetch","fetch-api","http","http-client","http2","library","nodejs","rfc-7234","stream"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adobe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-11-25T15:39:35.000Z","updated_at":"2026-06-23T09:00:57.000Z","dependencies_parsed_at":"2026-06-23T12:00:55.268Z","dependency_job_id":null,"html_url":"https://github.com/adobe/fetch","commit_stats":{"total_commits":453,"total_committers":14,"mean_commits":"32.357142857142854","dds":0.7130242825607064,"last_synced_commit":"d0f5a5f0c6b963abf91ff34654b1422e4d1cda70"},"previous_names":["adobe/helix-fetch"],"tags_count":95,"template":false,"template_full_name":null,"purl":"pkg:github/adobe/fetch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Ffetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Ffetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Ffetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Ffetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adobe","download_url":"https://codeload.github.com/adobe/fetch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adobe%2Ffetch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36170392,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-08-01T02:00:05.789Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","fetch","fetch-api","http","http-client","http2","library","nodejs","rfc-7234","stream"],"created_at":"2026-08-01T21:03:08.602Z","updated_at":"2026-08-01T21:03:09.239Z","avatar_url":"https://github.com/adobe.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"banner.jpeg\" alt=\"Adobe Fetch\"/\u003e\n  \u003cbr\u003e\n  \u003cp\u003eLight-weight \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\"\u003eFetch API\u003c/a\u003e implementation transparently supporting both \u003cb\u003eHTTP/1(.1)\u003c/b\u003e and \u003cb\u003eHTTP/2\u003c/b\u003e\u003c/p\u003e\n  \u003ca href=\"https://codecov.io/gh/adobe/fetch\"\u003e\u003cimg src=\"https://img.shields.io/codecov/c/github/adobe/fetch.svg\" alt=\"codecov\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://circleci.com/gh/adobe/fetch\"\u003e\u003cimg src=\"https://img.shields.io/circleci/project/github/adobe/fetch.svg\" alt=\"CircleCI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/adobe/fetch/blob/main/LICENSE.txt\"\u003e\u003cimg src=\"https://img.shields.io/github/license/adobe/fetch.svg\" alt=\"GitHub license\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/adobe/fetch/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/adobe/fetch.svg\" alt=\"GitHub issues\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://renovatebot.com/\"\u003e\u003cimg src=\"https://img.shields.io/badge/renovate-enabled-brightgreen.svg\" alt=\"Renovate enabled\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003e\u003cimg src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\" alt=\"semantic-release\"\u003e\u003c/a\u003e\n\t\u003ca href=\"https://packagephobia.now.sh/result?p=@adobe/fetch\"\u003e\u003cimg src=\"https://badgen.net/packagephobia/install/@adobe/fetch\" alt=\"Install size\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@adobe/fetch\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@adobe/fetch\" alt=\"Current version\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n---\n\n\u003c!-- TOC --\u003e\n- [About](#about)\n- [Features](#features)\n- [ESM/CJS support](#esmcjs-support)\n- [Installation](#installation)\n- [API](#api)\n  - [Context](#context)\n- [Common Usage Examples](#common-usage-examples)\n  - [Access Response Headers and other Meta data](#access-response-headers-and-other-meta-data)\n  - [Fetch JSON](#fetch-json)\n  - [Fetch text data](#fetch-text-data)\n  - [Fetch binary data](#fetch-binary-data)\n  - [Specify a timeout for a `fetch` operation](#specify-a-timeout-for-a-fetch-operation)\n  - [Stream an image](#stream-an-image)\n  - [Post JSON](#post-json)\n  - [Post JPEG image](#post-jpeg-image)\n  - [Post form data](#post-form-data)\n  - [GET with query parameters object](#get-with-query-parameters-object)\n  - [Cache](#cache)\n- [Advanced Usage Examples](#advanced-usage-examples)\n  - [HTTP/2 Server Push](#http2-server-push)\n  - [Use h2c (http2 cleartext w/prior-knowledge) protocol](#use-h2c-http2-cleartext-wprior-knowledge-protocol)\n  - [Force HTTP/1(.1) protocol](#force-http11-protocol)\n  - [HTTP/1.1 Keep-Alive](#http11-keep-alive)\n  - [Extract Set-Cookie Header](#extract-set-cookie-header)\n  - [Self-signed Certificates](#self-signed-certificates)\n  - [Set cache size limit](#set-cache-size-limit)\n  - [Disable caching](#disable-caching)\n  - [Set a custom user agent](#set-a-custom-user-agent)\n- [More examples](#more-examples)\n- [Development](#development)\n  - [Build](#build)\n  - [Test](#test)\n  - [Lint](#lint)\n  - [Troubleshooting](#troubleshooting)\n- [Acknowledgement](#acknowledgement)\n- [License](#license)\n\u003c!-- /TOC --\u003e\n\n---\n\n## About\n\n`@adobe/fetch` in general adheres to the [Fetch API Specification](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), implementing a subset of the API. However, there are some notable deviations:\n\n* `Response.body` returns a Node.js [Readable stream](https://nodejs.org/api/stream.html#stream_readable_streams).\n* `Response.blob()` is not implemented. Use `Response.buffer()` instead.\n* `Response.formData()` is not implemented.\n* Cookies are not stored by default. However, cookies can be extracted and passed by manipulating request and response headers.\n* The following values of the `fetch()` option `cache` are supported: `'default'` (the implicit default) and `'no-store'`. All other values are currently ignored.  \n* The following `fetch()` options are ignored due to the nature of Node.js and since `@adobe/fetch` doesn't have the concept of web pages: `mode`, `referrer`, `referrerPolicy`, `integrity` and `credentials`.\n* The `fetch()` option `keepalive` is not supported. But you can use the `h1.keepAlive` context option, as demonstrated [here](#http11-keep-alive).\n\n`@adobe/fetch` also supports the following non-spec extensions:\n\n* `Response.buffer()` returns a Node.js `Buffer`.\n* `Response.url` contains the final url when following redirects.\n* The `body` that can be sent in a `Request` can also be a `Readable` Node.js stream, a `Buffer`, a string or a plain object.\n* There are no forbidden header names.\n* The `Response` object has an extra property `httpVersion` which is one of `'1.0'`, `'1.1'` or `'2.0'`, depending on what was negotiated with the server.\n* The `Response` object has an extra property `fromCache` which determines whether the response was retrieved from cache.\n* The `Response` object has an extra property `decoded` which determines whether the response body was automatically decoded (see Fetch option `decode` below).\n* `Response.headers.plain()` returns the headers as a plain object.\n* `Response.headers.raw()` returns the internal/raw representation of the headers where e.g. the `Set-Cokkie` header is represented with an array of strings value.\n* The Fetch option `follow` allows to limit the number of redirects to follow (default: `20`).\n* The Fetch option `compress` enables transparent gzip/deflate/br content encoding (default: `true`).\n* The Fetch option `decode` enables transparent gzip/deflate/br content decoding (default: `true`).\n\nNote that non-standard Fetch options have been aligned with [node-fetch](https://github.com/node-fetch/node-fetch) where appropriate.\n  \n## Features\n\n* [x] supports reasonable subset of the standard [Fetch specification](https://fetch.spec.whatwg.org/)\n* [x] Transparent handling of HTTP/1(.1) and HTTP/2 connections\n* [x] [RFC 7234](https://httpwg.org/specs/rfc7234.html) compliant cache\n* [x] Support `gzip/deflate/br` content encoding\n* [x] HTTP/2 request and response multiplexing support\n* [x] HTTP/2 Server Push support (transparent caching and explicit listener support)\n* [x] overridable User-Agent\n* [x] low-level HTTP/1.* agent/connect options support (e.g. `keepAlive`, `rejectUnauthorized`)\n\n\n## ESM/CJS support\n\nThis package is native [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) and no longer provides CommonJS exports. Use `3.x` version if you still need to use this package with CommonJS.\n\n## Installation\n\n\u003e **Note**:\n\u003e\n\u003e As of v4 Node version \u003e= 14.16 is required.\n\n```bash\n$ npm install @adobe/fetch\n```\n\n## API\n\nApart from the standard Fetch API\n\n* `fetch()`\n* `Request`\n* `Response`\n* `Headers`\n* `Body`\n\n`@adobe/fetch` exposes the following non-spec extensions:\n\n* `context()` - creates a new customized API context\n* `reset()` - resets the current API context, i.e. closes pending sessions/sockets, clears internal caches, etc ...\n* `onPush()` - registers an HTTP/2 Server Push listener\n* `offPush()`- deregisters a listener previously registered with `onPush()`\n* `clearCache()` - clears the HTTP cache (cached responses)\n* `cacheStats()` - returns cache statistics\n* `noCache()` - creates a customized API context with disabled caching (_convenience_)\n* `h1()` - creates a customized API context with enforced HTTP/1.1 protocol (_convenience_)\n* `keepAlive()` - creates a customized API context with enforced HTTP/1.1 protocol and persistent connections (_convenience_)\n* `h1NoCache()` - creates a customized API context with disabled caching and enforced HTTP/1.1 protocol (_convenience_)\n* `keepAliveNoCache()` - creates a customized API context with disabled caching and enforced HTTP/1.1 protocol with persistent connections (_convenience_)\n* `createUrl()` - creates a URL with query parameters (_convenience_)\n* `timeoutSignal()` - ceates a timeout signal (_convenience_)\n\n### Context\n\nAn API context allows to customize certain aspects of the implementation and provides isolation of internal structures (session caches, HTTP cache, etc.) per API context.\n\nThe following options are supported:\n\n```ts\ninterface ContextOptions {\n  /**\n   * Value of `user-agent` request header\n   * @default 'adobe-fetch/\u003cversion\u003e'\n   */\n  userAgent?: string;\n  /**\n   * The maximum total size of the cached entries (in bytes). 0 disables caching.\n   * @default 100 * 1024 * 1024\n   */\n  maxCacheSize?: number;\n  /**\n   * The protocols to be negotiated, in order of preference\n   * @default [ALPN_HTTP2, ALPN_HTTP1_1, ALPN_HTTP1_0]\n   */\n  alpnProtocols?: ReadonlyArray\u003c ALPNProtocol \u003e;\n  /**\n   * How long (in milliseconds) should ALPN information be cached for a given host?\n   * @default 60 * 60 * 1000\n   */\n  alpnCacheTTL?: number;\n  /**\n   * (HTTPS only, applies to HTTP/1.x and HTTP/2)\n   * If not false, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails; err.code contains the OpenSSL error code.\n   * @default true\n   */\n  rejectUnauthorized?: boolean;\n  /**\n   * Maximum number of ALPN cache entries\n   * @default 100\n   */\n  alpnCacheSize?: number;\n  h1?: Http1Options;\n  h2?: Http2Options;\n};\n\ninterface Http1Options {\n  /**\n   * Keep sockets around in a pool to be used by other requests in the future.\n   * @default false\n   */\n  keepAlive?: boolean;\n  /**\n   * When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive.\n   * Only relevant if keepAlive is set to true.\n   * @default 1000\n   */\n  keepAliveMsecs?: number;\n  /**\n   * (HTTPS only)\n   * If not false, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails; err.code contains the OpenSSL error code.\n   * @default true\n   */\n  rejectUnauthorized?: boolean;\n  /**\n   * (HTTPS only)\n   * Maximum number of TLS cached sessions. Use 0 to disable TLS session caching.\n   * @default 100\n   */\n  maxCachedSessions?: number;\n}\n\ninterface Http2Options {\n  /**\n   * Max idle time in milliseconds after which a session will be automatically closed. \n   * @default 5 * 60 * 1000\n   */\n  idleSessionTimeout?: number;\n  /**\n   * Enable HTTP/2 Server Push?\n   * @default true\n   */\n  enablePush?: boolean;\n  /**\n   * Max idle time in milliseconds after which a pushed stream will be automatically closed. \n   * @default 5000\n   */\n  pushedStreamIdleTimeout?: number;\n  /**\n   * (HTTPS only)\n   * If not false, the server certificate is verified against the list of supplied CAs. An 'error' event is emitted if verification fails; err.code contains the OpenSSL error code.\n   * @default true\n   */\n  rejectUnauthorized?: boolean;\n};\n```\n\n## Common Usage Examples\n\n### Access Response Headers and other Meta data\n\n```javascript\n  import { fetch } from '@adobe/fetch';\n\n  const resp = await fetch('https://httpbin.org/get');\n  console.log(resp.ok);\n  console.log(resp.status);\n  console.log(resp.statusText);\n  console.log(resp.httpVersion);\n  console.log(resp.headers.plain());\n  console.log(resp.headers.get('content-type'));\n```\n\n### Fetch JSON\n\n```javascript\n  import { fetch } from '@adobe/fetch';\n\n  const resp = await fetch('https://httpbin.org/json');\n  const jsonData = await resp.json();\n```\n\n### Fetch text data\n\n```javascript\n  import { fetch } from '@adobe/fetch';\n\n  const resp = await fetch('https://httpbin.org/');\n  const textData = await resp.text();\n```\n\n### Fetch binary data\n\n```javascript\n  import { fetch } from '@adobe/fetch';\n\n  const resp = await fetch('https://httpbin.org//stream-bytes/65535');\n  const imageData = await resp.buffer();\n```\n\n### Specify a timeout for a `fetch` operation\n\nUsing `timeoutSignal(ms)` non-spec extension:\n\n```javascript\n  import { fetch, timeoutSignal, AbortError } from '@adobe/fetch';\n\n  const signal = timeoutSignal(1000);\n  try {\n    const resp = await fetch('https://httpbin.org/json', { signal });\n    const jsonData = await resp.json();\n  } catch (err) {\n    if (err instanceof AbortError) {\n      console.log('fetch timed out after 1s');\n    }\n  } finally {\n    // avoid pending timers which prevent node process from exiting\n    signal.clear();\n  }\n```\n\nUsing `AbortController`:\n\n```javascript\n  import { fetch, AbortController, AbortError } from '@adobe/fetch';\n\n  const controller = new AbortController();\n  const timerId = setTimeout(() =\u003e controller.abort(), 1000);\n  const { signal } = controller;\n\n  try {\n    const resp = await fetch('https://httpbin.org/json', { signal });\n    const jsonData = await resp.json();\n  } catch (err) {\n    if (err instanceof AbortError) {\n      console.log('fetch timed out after 1s');\n    }\n  } finally {\n    // avoid pending timers which prevent node process from exiting\n    clearTimeout(timerId);\n  }\n```\n\n### Stream an image\n\n```javascript\n  import { createWriteStream } from 'fs';\n  import { fetch } from '@adobe/fetch';\n\n  const resp = await fetch('https://httpbin.org/image/jpeg');\n  resp.body.pipe(createWriteStream('saved-image.jpg'));\n```\n\n### Post JSON\n\n```javascript\n  import { fetch } from '@adobe/fetch';\n\n  const method = 'POST';\n  const body = { foo: 'bar' };\n  const resp = await fetch('https://httpbin.org/post', { method, body });\n```\n\n### Post JPEG image\n\n```javascript\n  import { createReadStream } from 'fs';\n  import { fetch } from '@adobe/fetch';\n\n  const method = 'POST';\n  const body = createReadStream('some-image.jpg');\n  const headers = { 'content-type': 'image/jpeg' };\n  const resp = await fetch('https://httpbin.org/post', { method, body, headers });\n```\n\n### Post form data\n\n```javascript\n  import { FormData, Blob, File } from 'formdata-node'; // spec-compliant implementations\n  import { fileFromPath } from 'formdata-node/file-from-path'; // helper for creating File instance from disk file\n\n  import { fetch } from '@adobe/fetch';\n\n  const method = 'POST';\n  const fd = new FormData();\n  fd.set('field1', 'foo');\n  fd.set('field2', 'bar');\n  fd.set('blob', new Blob([0x68, 0x65, 0x6c, 0x69, 0x78, 0x2d, 0x66, 0x65, 0x74, 0x63, 0x68]));\n  fd.set('file', new File(['File content goes here'], 'file.txt'));\n  fd.set('other_file', await fileFromPath('/foo/bar.jpg', 'bar.jpg', { type: 'image/jpeg' }));\n  const resp = await fetch('https://httpbin.org/post', { method, body: fd });\n```\n\n### GET with query parameters object\n\n```javascript\nimport { createUrl, fetch } from '@adobe/fetch';\n\nconst qs = {\n  fake: 'dummy',\n  foo: 'bar',\n  rumple: \"stiltskin\",\n};\n\nconst resp = await fetch(createUrl('https://httpbin.org/json', qs));\n```\n\nor using `URLSearchParams`:\n\n```javascript\nimport { fetch } from '@adobe/fetch';\n\nconst body = new URLSearchParams({\n  fake: 'dummy',\n  foo: 'bar',\n  rumple: \"stiltskin\",\n});\n\nconst resp = await fetch('https://httpbin.org/json', { body });\n```\n\n### Cache\n\nResponses of `GET` and `HEAD` requests are by default cached, according to the rules of [RFC 7234](https://httpwg.org/specs/rfc7234.html):\n\n```javascript\nimport { fetch } from '@adobe/fetch';\n\nconst url = 'https://httpbin.org/cache/60'; // -\u003e max-age=60 (seconds)\n// send initial request, priming cache\nlet resp = await fetch(url);\nassert(resp.ok);\nassert(!resp.fromCache);\n\n// re-send request and verify it's served from cache\nresp = await fetch(url);\nassert(resp.ok);\nassert(resp.fromCache);\n```\n\nYou can disable caching per request with the `cache: 'no-store'` option:\n\n```javascript\nimport { fetch } from '@adobe/fetch';\n\nconst resp = await fetch('https://httbin.org/', { cache: 'no-store' });\nassert(resp.ok);\nassert(!resp.fromCache);\n```\n\nYou can disable caching entirely:\n\n```javascript\nimport { noCache } from '@adobe/fetch';\nconst { fetch } = noCache();\n```\n\n## Advanced Usage Examples\n\n### HTTP/2 Server Push\n\nNote that pushed resources will be automatically and transparently added to the cache.\nYou can however add a listener which will be notified on every pushed (and cached) resource.\n\n```javascript\n  import { fetch, onPush } from '@adobe/fetch';\n\n  onPush((url, response) =\u003e console.log(`received server push: ${url} status ${response.status}`));\n\n  const resp = await fetch('https://nghttp2.org');\n  console.log(`Http version: ${resp.httpVersion}`);\n```\n\n### Use h2c (http2 cleartext w/prior-knowledge) protocol\n\n```javascript\n  import { fetch } from '@adobe/fetch';\n\n  const resp = await fetch('http2://nghttp2.org');\n  console.log(`Http version: ${resp.httpVersion}`);\n```\n\n### Force HTTP/1(.1) protocol\n\n```javascript\n  import { h1 } from '@adobe/fetch';\n  const { fetch } = h1();\n\n  const resp = await fetch('https://nghttp2.org');\n  console.log(`Http version: ${resp.httpVersion}`);\n```\n\n### HTTP/1.1 Keep-Alive\n\n```javascript\nimport { keepAlive } from '@adobe/fetch';\nconst { fetch } = keepAlive();\n\nconst resp = await fetch('https://httpbin.org/status/200');\nconsole.log(`Connection: ${resp.headers.get('connection')}`); // -\u003e keep-alive\n```\n\n### Extract Set-Cookie Header\n\nUnlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is an `@adobe/fetch` only API.\n\n```javascript\nimport { fetch } from '@adobe/fetch';\n\nconst resp = await fetch('https://httpbin.org/cookies/set?a=1\u0026b=2');\n// returns an array of values, instead of a string of comma-separated values\nconsole.log(resp.headers.raw()['set-cookie']);\n```\n\n### Self-signed Certificates\n\n```javascript\nimport { context } from '@adobe/fetch';\nconst { fetch } = context({ rejectUnauthorized: false });\n\nconst resp = await fetch('https://localhost:8443/');  // a server using a self-signed certificate\n```\n\n### Set cache size limit\n\n```javascript\n  import { context } from '@adobe/fetch';\n  const { fetch } = context({\n    maxCacheSize: 100 * 1024, // 100kb (Default: 100mb)\n  });\n\n  let resp = await fetch('https://httpbin.org/bytes/60000'); // ~60kb response\n  resp = await fetch('https://httpbin.org/bytes/50000'); // ~50kb response\n  console.log(cacheStats());\n```\n\n### Disable caching\n\n```javascript\n  import { noCache } from '@adobe/fetch';\n  const { fetch } = noCache();\n\n  let resp = await fetch('https://httpbin.org/cache/60'); // -\u003e max-age=60 (seconds)\n  // re-fetch\n  resp = await fetch('https://httpbin.org/cache/60');\n  assert(!resp.fromCache);\n```\n\n### Set a custom user agent\n\n```javascript\n  import { context } from '@adobe/fetch';\n  const { fetch } = context({\n    userAgent: 'custom-fetch'\n  });\n\n  const resp = await fetch('https://httpbin.org//user-agent');\n  const json = await resp.json();\n  console.log(json['user-agent']);\n```\n\n## More examples\n\nMore example code can be found in the [test source files](/test/).\n\n## Development\n\n### Build\n\n```bash\n$ npm install\n```\n\n### Test\n\n```bash\n$ npm test\n```\n\n### Lint\n\n```bash\n$ npm run lint\n```\n\n### Troubleshooting\n\nYou can enable `@adobe/fetch` low-level debug console output by setting the `DEBUG` environment variable to `adobe/fetch*`, e.g.:\n\n```bash\n$ DEBUG=adobe/fetch* node test.js\n```\n\nThis will produce console outout similar to:\n\n```bash\n  ...\n  adobe/fetch:core established TLS connection: #48 (www.nghttp2.org) +2s\n  adobe/fetch:core www.nghttp2.org -\u003e h2 +0ms\n  adobe/fetch:h2 reusing socket #48 (www.nghttp2.org) +2s\n  adobe/fetch:h2 GET www.nghttp2.org/httpbin/user-agent +0ms\n  adobe/fetch:h2 session https://www.nghttp2.org established +1ms\n  adobe/fetch:h2 caching session https://www.nghttp2.org +0ms\n  adobe/fetch:h2 session https://www.nghttp2.org remoteSettings: {\"headerTableSize\":8192,\"enablePush\":true,\"initialWindowSize\":1048576,\"maxFrameSize\":16384,\"maxConcurrentStreams\":100,\"maxHeaderListSize\":4294967295,\"maxHeaderSize\":4294967295,\"enableConnectProtocol\":true} +263ms\n  adobe/fetch:h2 session https://www.nghttp2.org localSettings: {\"headerTableSize\":4096,\"enablePush\":true,\"initialWindowSize\":65535,\"maxFrameSize\":16384,\"maxConcurrentStreams\":4294967295,\"maxHeaderListSize\":4294967295,\"maxHeaderSize\":4294967295,\"enableConnectProtocol\":false} +0ms\n  adobe/fetch:h2 session https://www.nghttp2.org closed +6ms\n  adobe/fetch:h2 discarding cached session https://www.nghttp2.org +0ms\n  ... \n```\n\nAdditionally, you can enable Node.js low-level debug console output by setting the `NODE_DEBUG` environment variable appropriately, e.g.\n\n```bash\n$ export NODE_DEBUG=http*,stream*\n$ export DEBUG=adobe/fetch*\n\n$ node test.js\n```\n\n\u003e Note: this will flood the console with highly verbose debug output.\n\n## Acknowledgement\n\nThanks to [node-fetch](https://github.com/node-fetch/node-fetch) and [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference.\n\n## License\n\n[Apache 2.0](LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadobe%2Ffetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadobe%2Ffetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadobe%2Ffetch/lists"}