Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: metcoder95/undici
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: nodejs/undici
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Mar 21, 2025

  1. test: disable header de-duplication in test servers (nodejs#4110)

    Closes nodejs#4109
    
    Co-authored-by: alxndrsn <alxndrsn>
    alxndrsn authored Mar 21, 2025
    Copy the full SHA
    85b8c57 View commit details
  2. chore: CacheRevalidationHandler extend comment (nodejs#4111)

    Include if-not-modified as a potential header which can tell the origin we want to revlidate.
    
    Co-authored-by: alxndrsn <alxndrsn>
    alxndrsn authored Mar 21, 2025
    Copy the full SHA
    2df904f View commit details

Commits on Mar 23, 2025

  1. Copy the full SHA
    c584721 View commit details

Commits on Mar 26, 2025

  1. build(deps-dev): bump @matteo.collina/tspl from 0.1.1 to 0.2.0 (nodej…

    …s#4119)
    
    Bumps [@matteo.collina/tspl](https://github.com/mcollina/tspl) from 0.1.1 to 0.2.0.
    - [Release notes](https://github.com/mcollina/tspl/releases)
    - [Commits](mcollina/tspl@v0.1.1...v0.2.0)
    
    ---
    updated-dependencies:
    - dependency-name: "@matteo.collina/tspl"
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Mar 26, 2025
    Copy the full SHA
    794b342 View commit details
  2. fix 4105 (nodejs#4117)

    * fix 4105
    
    * skip < node v22
    KhafraDev authored Mar 26, 2025
    Copy the full SHA
    0ba30ce View commit details

Commits on Mar 27, 2025

  1. chore: update WPT (nodejs#4100)

    Co-authored-by: Uzlopak <5059100+Uzlopak@users.noreply.github.com>
    github-actions[bot] and Uzlopak authored Mar 27, 2025
    Copy the full SHA
    33daab9 View commit details
  2. cache: ensure vary & revalidation headers are case-insensitive (nodej…

    …s#4112)
    
    Closes nodejs#4103
    
    Co-authored-by: alxndrsn <alxndrsn>
    alxndrsn authored Mar 27, 2025
    Copy the full SHA
    fa959b8 View commit details
  3. Bumped v7.6.0

    Signed-off-by: Matteo Collina <hello@matteocollina.com>
    mcollina committed Mar 27, 2025
    Copy the full SHA
    9d5e8ba View commit details
  4. Copy the full SHA
    242ec9b View commit details

Commits on Mar 28, 2025

  1. Copy the full SHA
    1866f1f View commit details

Commits on Mar 31, 2025

  1. chore: update WPT (nodejs#4126)

    Co-authored-by: Uzlopak <5059100+Uzlopak@users.noreply.github.com>
    github-actions[bot] and Uzlopak authored Mar 31, 2025
    Copy the full SHA
    73916b3 View commit details
  2. Copy the full SHA
    67adf42 View commit details

Commits on Apr 2, 2025

  1. feat: implement h2c client (nodejs#4118)

    * feat: implement h2c client
    
    * refactor: connect timeout utils
    
    * feat: implement socket handling intrinsics
    
    * test: enhance testing
    
    * types: export typing
    
    * refactor: cleanup
    
    * refactor: Update test/h2c-client.js
    
    Co-authored-by: Matteo Collina <hello@matteocollina.com>
    
    * docs: adjust documentation
    
    * feat: limit pipelining to max concurrent streams
    
    * fix: bad statement
    
    ---------
    
    Co-authored-by: Matteo Collina <hello@matteocollina.com>
    metcoder95 and mcollina authored Apr 2, 2025
    Copy the full SHA
    1749556 View commit details
  2. Bumped v7.7.0 (nodejs#4138)

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
    github-actions[bot] authored Apr 2, 2025
    Copy the full SHA
    981636f View commit details

Commits on Apr 4, 2025

  1. Copy the full SHA
    8a5de7c View commit details
  2. skip now failing tests (nodejs#4145)

    Signed-off-by: Matteo Collina <hello@matteocollina.com>
    mcollina authored Apr 4, 2025
    Copy the full SHA
    e0058a7 View commit details

Commits on Apr 5, 2025

  1. Copy the full SHA
    c8acc81 View commit details

Commits on Apr 7, 2025

  1. types(websocket): Import from stream/web (nodejs#4038)

    * types(websocket): Import from stream/web
    
    * test: Ensure types are from stream/web
    Jiralite authored Apr 7, 2025
    Copy the full SHA
    d2be897 View commit details
  2. cache: don't check size if not necessary (nodejs#4140)

    * cache: don't check size if not necessary
    
    * Update lib/cache/sqlite-cache-store.js
    
    ---------
    
    Co-authored-by: Matteo Collina <hello@matteocollina.com>
    ronag and mcollina authored Apr 7, 2025
    Copy the full SHA
    03c497c View commit details

Commits on Apr 8, 2025

  1. Copy the full SHA
    9dd11b8 View commit details

Commits on Apr 10, 2025

  1. chore: update WPT (nodejs#4141)

    Co-authored-by: Uzlopak <5059100+Uzlopak@users.noreply.github.com>
    github-actions[bot] and Uzlopak authored Apr 10, 2025
    Copy the full SHA
    a113b90 View commit details
  2. build(deps-dev): bump esbuild from 0.24.2 to 0.25.2 (nodejs#4130)

    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 10, 2025
    Copy the full SHA
    c29be3b View commit details
  3. Bumped v7.8.0 (nodejs#4154)

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
    github-actions[bot] authored Apr 10, 2025
    Copy the full SHA
    6ea61af View commit details

Commits on Apr 13, 2025

  1. build(deps): bump step-security/harden-runner from 2.10.2 to 2.11.1 (n…

    …odejs#4134)
    
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 13, 2025
    Copy the full SHA
    59558c8 View commit details

Commits on Apr 15, 2025

  1. chore: update WPT (nodejs#4155)

    Co-authored-by: Uzlopak <5059100+Uzlopak@users.noreply.github.com>
    github-actions[bot] and Uzlopak authored Apr 15, 2025
    Copy the full SHA
    436e749 View commit details

Commits on Apr 20, 2025

  1. Copy the full SHA
    259d5f8 View commit details

Commits on Apr 21, 2025

  1. feat: add new acceptNonStandardSearchParameters MockAgent option (n…

    …odejs#4148)
    
    Co-authored-by: Carlos Fuentes <me@metcoder.dev>
    dario-piotrowicz and metcoder95 authored Apr 21, 2025
    Copy the full SHA
    0daba93 View commit details

Commits on Apr 23, 2025

  1. fix: cache: treat cache-control request header case-insensitively (no…

    …dejs#4131)
    
    * fix: cache: treat cache-control request header case-insensitively
    
    Closes nodejs#3904
    
    * lint; close server after test
    
    * call normaliseHeaders() once
    
    * revert unnecessary change
    
    ---------
    
    Co-authored-by: alxndrsn <alxndrsn>
    alxndrsn authored Apr 23, 2025
    Copy the full SHA
    fe7aa83 View commit details
  2. cache: honour unqualified no-cache response directive (nodejs#4178)

    * cache: honour unqualified no-cache response directive
    
    Closes nodejs#4173
    
    * move test to interceptors/cache.js
    
    * lint
    
    * remove duplicate close()
    
    ---------
    
    Co-authored-by: alxndrsn <alxndrsn>
    alxndrsn authored Apr 23, 2025
    Copy the full SHA
    c0e634d View commit details

Commits on Apr 24, 2025

  1. build(deps): bump ossf/scorecard-action from 2.4.0 to 2.4.1 (nodejs#4079

    )
    
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Apr 24, 2025
    Copy the full SHA
    14e62db View commit details
Showing with 2,744 additions and 1,655 deletions.
  1. +1 −1 .github/workflows/codeql.yml
  2. +1 −1 .github/workflows/nodejs.yml
  3. +1 −1 .github/workflows/scorecard.yml
  4. +1 −1 docs/docs/api/Agent.md
  5. +1 −1 docs/docs/api/Dispatcher.md
  6. +262 −0 docs/docs/api/H2CClient.md
  7. +3 −1 docs/docs/api/MockAgent.md
  8. +1 −0 docs/docsify/sidebar.md
  9. +12 −8 docs/examples/README.md
  10. +2 −0 index.js
  11. +8 −4 lib/cache/sqlite-cache-store.js
  12. +2 −78 lib/core/connect.js
  13. +78 −2 lib/core/util.js
  14. +1 −0 lib/dispatcher/client-h2.js
  15. +122 −0 lib/dispatcher/h2c-client.js
  16. +1 −1 lib/handler/cache-revalidation-handler.js
  17. +12 −2 lib/interceptor/cache.js
  18. +14 −2 lib/mock/mock-agent.js
  19. +1 −0 lib/mock/mock-symbols.js
  20. +37 −3 lib/mock/mock-utils.js
  21. +15 −7 lib/util/cache.js
  22. +4 −3 lib/web/fetch/index.js
  23. +4 −4 package.json
  24. +1 −1 test/client-connect.js
  25. +1 −1 test/client-head-reset-override.js
  26. +1 −1 test/client-idempotent-body.js
  27. +1 −1 test/client-keep-alive.js
  28. +1 −1 test/client-node-max-header-size.js
  29. +30 −30 test/client-pipeline.js
  30. +12 −12 test/client-pipelining.js
  31. +2 −2 test/client-post.js
  32. +1 −1 test/client-reconnect.js
  33. +40 −40 test/client-request.js
  34. +22 −22 test/client-stream.js
  35. +4 −4 test/client-timeout.js
  36. +1 −1 test/client-unref.js
  37. +9 −9 test/client-upgrade.js
  38. +1 −1 test/client-write-max-listeners.js
  39. +52 −52 test/client.js
  40. +9 −9 test/close-and-destroy.js
  41. +1 −1 test/connect-pre-shared-session.js
  42. +8 −8 test/content-length.js
  43. +2 −2 test/env-http-proxy-agent-nodejs-bundle.js
  44. +1 −1 test/eventsource/eventsource-attributes.js
  45. +2 −2 test/eventsource/eventsource-close.js
  46. +8 −8 test/eventsource/eventsource-connect.js
  47. +1 −1 test/eventsource/eventsource-constructor-stringify.js
  48. +2 −2 test/eventsource/eventsource-constructor.js
  49. +1 −1 test/eventsource/eventsource-custom-dispatcher.js
  50. +9 −9 test/eventsource/eventsource-message.js
  51. +4 −4 test/eventsource/eventsource-reconnect.js
  52. +5 −5 test/eventsource/eventsource-redirecting.js
  53. +1 −1 test/eventsource/eventsource-request-status-error.js
  54. +2 −2 test/examples.js
  55. +1 −1 test/fetch/407-statuscode-window-null.js
  56. +1 −1 test/fetch/abort.js
  57. +1 −1 test/fetch/abort2.js
  58. +26 −26 test/fetch/client-fetch.js
  59. +1 −1 test/fetch/client-node-max-header-size.js
  60. +1 −1 test/fetch/content-length.js
  61. +3 −3 test/fetch/cookies.js
  62. +2 −2 test/fetch/encoding.js
  63. +1 −1 test/fetch/exiting.js
  64. +1 −1 test/fetch/fetch-leak.js
  65. +1 −1 test/fetch/fetch-timeouts.js
  66. +2 −2 test/fetch/fetch-url-after-redirect.js
  67. +1 −1 test/fetch/fire-and-forget.js
  68. +1 −1 test/fetch/headers-case.js
  69. +2 −2 test/fetch/headers.js
  70. +14 −14 test/fetch/integrity.js
  71. +2 −2 test/fetch/issue-1711.js
  72. +1 −1 test/fetch/issue-2009.js
  73. +1 −1 test/fetch/issue-2021.js
  74. +1 −1 test/fetch/issue-2171.js
  75. +1 −1 test/fetch/issue-2318.js
  76. +1 −1 test/fetch/issue-2828.js
  77. +1 −1 test/fetch/issue-2898-comment.js
  78. +1 −1 test/fetch/issue-2898.js
  79. +1 −1 test/fetch/issue-3334.js
  80. +1 −1 test/fetch/issue-3616.js
  81. +1 −1 test/fetch/issue-3624.js
  82. +1 −1 test/fetch/issue-3767.js
  83. +34 −0 test/fetch/issue-4105.js
  84. +1 −1 test/fetch/issue-node-46525.js
  85. +1 −1 test/fetch/issue-rsshub-15532.js
  86. +1 −1 test/fetch/long-lived-abort-controller.js
  87. +1 −1 test/fetch/pull-dont-push.js
  88. +2 −2 test/fetch/redirect-cross-origin-header.js
  89. +3 −3 test/fetch/redirect.js
  90. +1 −1 test/fetch/referrrer-policy.js
  91. +2 −2 test/fetch/relative-url.js
  92. +4 −4 test/fetch/resource-timing.js
  93. +1 −1 test/fetch/user-agent.js
  94. +3 −2 test/fixtures/cache-tests/test-engine/server/server.mjs
  95. +1 −1 test/fixtures/fetch.js
  96. +1 −1 test/fixtures/interceptors/retry-event-loop.js
  97. +1 −1 test/fixtures/undici.js
  98. +4 −0 test/fixtures/wpt/fetch/api/basic/WEB_FEATURES.yml
  99. +1 −1 test/fixtures/wpt/fetch/api/body/mime-type.any.js
  100. +1 −1 test/fixtures/wpt/fetch/api/resources/keepalive-helper.js
  101. +3 −0 test/fixtures/wpt/fetch/content-encoding/zstd/WEB_FEATURES.yml
  102. +1 −1 test/fixtures/wpt/fetch/http-cache/README.md
  103. +25 −2 test/fixtures/wpt/fetch/http-cache/heuristic.any.js
  104. +20 −6 test/fixtures/wpt/fetch/http-cache/http-cache.js
  105. +33 −0 test/fixtures/wpt/fetch/http-cache/no-vary-search.tentative.any.js
  106. +1 −1 test/fixtures/wpt/fetch/http-cache/split-cache.html
  107. +3 −0 test/fixtures/wpt/fetch/private-network-access/README.md
  108. +0 −91 ...res/wpt/fetch/private-network-access/fenced-frame-no-preflight-required.tentative.https.window.js
  109. +0 −330 ...ixtures/wpt/fetch/private-network-access/fenced-frame-subresource-fetch.tentative.https.window.js
  110. +0 −150 test/fixtures/wpt/fetch/private-network-access/fenced-frame.tentative.https.window.js
  111. +30 −16 ...itigation-allowed-apis.tentative.https.html → dangling-markup-mitigation-allowed-apis.https.html}
  112. +12 −1 test/fixtures/wpt/interfaces/dom.idl
  113. +4 −1 test/fixtures/wpt/interfaces/fedcm.idl
  114. +12 −2 test/fixtures/wpt/interfaces/html.idl
  115. +4 −4 test/fixtures/wpt/interfaces/ppa.idl
  116. +38 −0 test/fixtures/wpt/interfaces/scoped-custom-elements-registry.tentative.idl
  117. +1 −0 test/fixtures/wpt/interfaces/screen-capture.idl
  118. +9 −1 test/fixtures/wpt/interfaces/secure-payment-confirmation.idl
  119. +29 −2 test/fixtures/wpt/interfaces/speech-api.idl
  120. +2 −1 test/fixtures/wpt/interfaces/webaudio.idl
  121. +6 −2 test/fixtures/wpt/interfaces/webgpu.idl
  122. +100 −87 test/fixtures/wpt/interfaces/webnn.idl
  123. +11 −2 test/fixtures/wpt/interfaces/webrtc-stats.idl
  124. +12 −7 test/fixtures/wpt/interfaces/webrtc.idl
  125. +0 −1 test/fixtures/wpt/interfaces/webtransport.idl
  126. +9 −0 test/fixtures/wpt/interfaces/webxr-depth-sensing.idl
  127. +2 −0 test/fixtures/wpt/interfaces/webxr.idl
  128. +2 −0 test/fixtures/wpt/interfaces/webxrlayers.idl
  129. +9 −0 test/fixtures/wpt/resources/chromium/webxr-test.js
  130. +84 −5 test/fixtures/wpt/resources/testdriver.js
  131. +12 −8 test/fixtures/wpt/resources/testharness.js
  132. +1 −1 test/fixtures/wpt/service-workers/service-worker/claim-using-registration.https.html
  133. +129 −0 test/fixtures/wpt/service-workers/service-worker/client-url-creation-url.https.html
  134. +85 −0 test/fixtures/wpt/service-workers/service-worker/resources/client-url-creation-url-iframe.html
  135. +24 −0 test/fixtures/wpt/service-workers/service-worker/resources/client-url-creation-url-sw.js
  136. +1 −1 test/fixtures/wpt/service-workers/service-worker/resources/testharness-helpers.js
  137. +10 −5 ...t/service-workers/service-worker/tentative/static-router/static-router-resource-timing.https.html
  138. +2 −2 test/fixtures/wpt/service-workers/service-worker/unregister-immediately-before-installed.https.html
  139. +1 −1 test/fixtures/wpt/service-workers/service-worker/unregister-immediately.https.html
  140. +5 −0 test/fixtures/wpt/xhr/resources/redirect.py
  141. +61 −24 test/fixtures/wpt/xhr/send-redirect.htm
  142. +20 −18 test/fixtures/wpt/xhr/setrequestheader-case-insensitive.htm
  143. +2 −2 test/get-head-body.js
  144. +121 −0 test/h2c-client.js
  145. +6 −6 test/headers-as-array.js
  146. +1 −1 test/headers-crlf.js
  147. +5 −5 test/http-100.js
  148. +2 −2 test/http-req-destroy.js
  149. +7 −1 test/http2.js
  150. +2 −2 test/https.js
  151. +1 −1 test/inflight-and-close.js
  152. +1 −1 test/interceptors/cache-fastimers-fix.js
  153. +141 −38 test/interceptors/cache.js
  154. +21 −21 test/interceptors/dns.js
  155. +9 −9 test/interceptors/dump-interceptor.js
  156. +1 −1 test/interceptors/redirect-issue-3803.js
  157. +2 −2 test/interceptors/redirect.js
  158. +5 −5 test/interceptors/response-error.js
  159. +9 −9 test/interceptors/retry.js
  160. +1 −1 test/issue-2065.js
  161. +1 −1 test/issue-2590.js
  162. +1 −1 test/issue-3356.js
  163. +58 −0 test/issue-3904.js
  164. +1 −1 test/issue-3934.js
  165. +1 −1 test/issue-3959.js
  166. +1 −1 test/issue-803.js
  167. +1 −1 test/jest/instanceof-error.test.js
  168. +1 −1 test/jest/test.js
  169. +1 −1 test/max-headers.js
  170. +3 −3 test/max-response-size.js
  171. +142 −50 test/mock-agent.js
  172. +6 −6 test/mock-client.js
  173. +3 −3 test/mock-pool.js
  174. +32 −1 test/mock-utils.js
  175. +7 −7 test/no-strict-content-length.js
  176. +1 −1 test/node-fetch/main.js
  177. +1 −1 test/node-fetch/utils/server.js
  178. +8 −8 test/node-test/abort-controller.js
  179. +8 −8 test/node-test/abort-event-emitter.js
  180. +16 −16 test/node-test/agent.js
  181. +3 −3 test/node-test/async_hooks.js
  182. +6 −6 test/node-test/autoselectfamily.js
  183. +6 −6 test/node-test/balanced-pool.js
  184. +2 −2 test/node-test/ca-fingerprint.js
  185. +5 −5 test/node-test/client-abort.js
  186. +6 −6 test/node-test/client-connect.js
  187. +21 −21 test/node-test/client-dispatch.js
  188. +21 −21 test/node-test/client-errors.js
  189. +1 −1 test/node-test/diagnostics-channel/error.js
  190. +1 −1 test/node-test/diagnostics-channel/get.js
  191. +1 −1 test/node-test/diagnostics-channel/post-stream.js
  192. +1 −1 test/node-test/diagnostics-channel/post.js
  193. +1 −1 test/node-test/large-body.js
  194. +3 −3 test/node-test/unix.js
  195. +1 −1 test/node-test/validations.js
  196. +2 −2 test/pipeline-pipelining.js
  197. +1 −1 test/pool-connection-error-memory-leak.js
  198. +24 −24 test/pool.js
  199. +7 −7 test/promises.js
  200. +6 −4 test/proxy-agent.js
  201. +2 −2 test/proxy.js
  202. +1 −1 test/request-crlf.js
  203. +3 −3 test/request-signal.js
  204. +21 −21 test/request-timeout.js
  205. +1 −1 test/request-timeout2.js
  206. +13 −13 test/request.js
  207. +1 −1 test/retry-agent.js
  208. +19 −19 test/retry-handler.js
  209. +1 −1 test/socket-back-pressure.js
  210. +2 −2 test/socket-timeout.js
  211. +3 −3 test/stream-compat.js
  212. +2 −1 test/tls-cert-leak.js
  213. +2 −1 test/tls-session-reuse.js
  214. +2 −2 test/trailers.js
  215. +34 −0 test/types/dispatcher.test-d.ts
  216. +9 −0 test/types/mock-agent.test-d.ts
  217. +10 −0 test/types/websocket.test-d.ts
  218. +1 −1 test/utils/esm-wrapper.mjs
  219. +1 −1 test/utils/hello-world-server.js
  220. +1 −1 test/utils/redirecting-servers.js
  221. +7 −7 test/websocket/opening-handshake.js
  222. +1 −1 test/wpt/server/server.mjs
  223. +0 −8 test/wpt/status/fetch.status.json
  224. +4 −1 test/wpt/status/service-workers/cache-storage.status.json
  225. +5 −3 types/dispatcher.d.ts
  226. +75 −0 types/h2c-client.d.ts
  227. +3 −1 types/index.d.ts
  228. +3 −0 types/mock-agent.d.ts
  229. +1 −0 types/websocket.d.ts
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ jobs:

steps:
- name: Harden Runner
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
with:
egress-policy: audit

2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
with:
egress-policy: audit

2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ jobs:
persist-credentials: false

- name: "Run analysis"
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
with:
results_file: results.sarif
results_format: sarif
2 changes: 1 addition & 1 deletion docs/docs/api/Agent.md
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

Extends: `undici.Dispatcher`

Agent allow dispatching requests against multiple different origins.
Agent allows dispatching requests against multiple different origins.

Requests are not guaranteed to be dispatched in order of invocation.

2 changes: 1 addition & 1 deletion docs/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
@@ -194,7 +194,7 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo
* **method** `string`
* **reset** `boolean` (optional) - Default: `false` - If `false`, the request will attempt to create a long-living connection by sending the `connection: keep-alive` header,otherwise will attempt to close it immediately after response by sending `connection: close` within the request and closing the socket afterwards.
* **body** `string | Buffer | Uint8Array | stream.Readable | Iterable | AsyncIterable | null` (optional) - Default: `null`
* **headers** `UndiciHeaders | string[]` (optional) - Default: `null`.
* **headers** `UndiciHeaders` (optional) - Default: `null`.
* **query** `Record<string, any> | null` (optional) - Default: `null` - Query string params to be embedded in the request URL. Note that both keys and values of query are encoded using `encodeURIComponent`. If for some reason you need to send them unencoded, embed query params into path directly instead.
* **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline has completed.
* **blocking** `boolean` (optional) - Default: `method !== 'HEAD'` - Whether the response is expected to take a long time and would end up blocking the pipeline. When this is set to `true` further pipelining will be avoided on the same connection until headers have been received.
262 changes: 262 additions & 0 deletions docs/docs/api/H2CClient.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# Class: H2CClient

Extends: `undici.Dispatcher`

A basic H2C client.

**Example**

```js
const { createServer } = require('node:http2')
const { once } = require('node:events')
const { H2CClient } = require('undici')

const server = createServer((req, res) => {
res.writeHead(200)
res.end('Hello, world!')
})

server.listen()
once(server, 'listening').then(() => {
const client = new H2CClient(`http://localhost:${server.address().port}/`)

const response = await client.request({ path: '/', method: 'GET' })
console.log(response.statusCode) // 200
response.body.text.then((text) => {
console.log(text) // Hello, world!
})
})
```

## `new H2CClient(url[, options])`

Arguments:

- **url** `URL | string` - Should only include the **protocol, hostname, and port**. It only supports `http` protocol.
- **options** `H2CClientOptions` (optional)

Returns: `H2CClient`

### Parameter: `H2CClientOptions`

- **bodyTimeout** `number | null` (optional) - Default: `300e3` - The timeout after which a request will time out, in milliseconds. Monitors time between receiving body data. Use `0` to disable it entirely. Defaults to 300 seconds. Please note the `timeout` will be reset if you keep writing data to the socket everytime.
- **headersTimeout** `number | null` (optional) - Default: `300e3` - The amount of time, in milliseconds, the parser will wait to receive the complete HTTP headers while not sending the request. Defaults to 300 seconds.
- **keepAliveMaxTimeout** `number | null` (optional) - Default: `600e3` - The maximum allowed `keepAliveTimeout`, in milliseconds, when overridden by _keep-alive_ hints from the server. Defaults to 10 minutes.
- **keepAliveTimeout** `number | null` (optional) - Default: `4e3` - The timeout, in milliseconds, after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by _keep-alive_ hints from the server. See [MDN: HTTP - Headers - Keep-Alive directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive#directives) for more details. Defaults to 4 seconds.
- **keepAliveTimeoutThreshold** `number | null` (optional) - Default: `2e3` - A number of milliseconds subtracted from server _keep-alive_ hints when overriding `keepAliveTimeout` to account for timing inaccuracies caused by e.g. transport latency. Defaults to 2 seconds.
- **maxHeaderSize** `number | null` (optional) - Default: `--max-http-header-size` or `16384` - The maximum length of request headers in bytes. Defaults to Node.js' --max-http-header-size or 16KiB.
- **maxResponseSize** `number | null` (optional) - Default: `-1` - The maximum length of response body in bytes. Set to `-1` to disable.
- **maxConcurrentStreams**: `number` - Default: `100`. Dictates the maximum number of concurrent streams for a single H2 session. It can be overridden by a SETTINGS remote frame.
- **pipelining** `number | null` (optional) - Default to `maxConcurrentStreams` - The amount of concurrent requests sent over a single HTTP/2 session in accordance with [RFC-7540](https://httpwg.org/specs/rfc7540.html#StreamsLayer) Stream specification. Streams can be closed up by remote server at any time.
- **connect** `ConnectOptions | null` (optional) - Default: `null`.
- **strictContentLength** `Boolean` (optional) - Default: `true` - Whether to treat request content length mismatches as errors. If true, an error is thrown when the request content-length header doesn't match the length of the request body.
- **autoSelectFamily**: `boolean` (optional) - Default: depends on local Node version, on Node 18.13.0 and above is `false`. Enables a family autodetection algorithm that loosely implements section 5 of [RFC 8305](https://tools.ietf.org/html/rfc8305#section-5). See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details. This option is ignored if not supported by the current Node version.
- **autoSelectFamilyAttemptTimeout**: `number` - Default: depends on local Node version, on Node 18.13.0 and above is `250`. The amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the `autoSelectFamily` option. See [here](https://nodejs.org/api/net.html#socketconnectoptions-connectlistener) for more details.

#### Parameter: `H2CConnectOptions`

- **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
- **timeout** `number | null` (optional) - In milliseconds, Default `10e3`.
- **servername** `string | null` (optional)
- **keepAlive** `boolean | null` (optional) - Default: `true` - TCP keep-alive enabled
- **keepAliveInitialDelay** `number | null` (optional) - Default: `60000` - TCP keep-alive interval for the socket in milliseconds

### Example - Basic Client instantiation

This will instantiate the undici H2CClient, but it will not connect to the origin until something is queued. Consider using `client.connect` to prematurely connect to the origin, or just call `client.request`.

```js
"use strict";
import { H2CClient } from "undici";

const client = new H2CClient("http://localhost:3000");
```

## Instance Methods

### `H2CClient.close([callback])`

Implements [`Dispatcher.close([callback])`](/docs/docs/api/Dispatcher.md#dispatcherclosecallback-promise).

### `H2CClient.destroy([error, callback])`

Implements [`Dispatcher.destroy([error, callback])`](/docs/docs/api/Dispatcher.md#dispatcherdestroyerror-callback-promise).

Waits until socket is closed before invoking the callback (or returning a promise if no callback is provided).

### `H2CClient.connect(options[, callback])`

See [`Dispatcher.connect(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback).

### `H2CClient.dispatch(options, handlers)`

Implements [`Dispatcher.dispatch(options, handlers)`](/docs/docs/api/Dispatcher.md#dispatcherdispatchoptions-handler).

### `H2CClient.pipeline(options, handler)`

See [`Dispatcher.pipeline(options, handler)`](/docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler).

### `H2CClient.request(options[, callback])`

See [`Dispatcher.request(options [, callback])`](/docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback).

### `H2CClient.stream(options, factory[, callback])`

See [`Dispatcher.stream(options, factory[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback).

### `H2CClient.upgrade(options[, callback])`

See [`Dispatcher.upgrade(options[, callback])`](/docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback).

## Instance Properties

### `H2CClient.closed`

- `boolean`

`true` after `H2CClient.close()` has been called.

### `H2CClient.destroyed`

- `boolean`

`true` after `client.destroyed()` has been called or `client.close()` has been called and the client shutdown has completed.

### `H2CClient.pipelining`

- `number`

Property to get and set the pipelining factor.

## Instance Events

### Event: `'connect'`

See [Dispatcher Event: `'connect'`](/docs/docs/api/Dispatcher.md#event-connect).

Parameters:

- **origin** `URL`
- **targets** `Array<Dispatcher>`

Emitted when a socket has been created and connected. The client will connect once `client.size > 0`.

#### Example - Client connect event

```js
import { createServer } from "node:http2";
import { H2CClient } from "undici";
import { once } from "events";

const server = createServer((request, response) => {
response.end("Hello, World!");
}).listen();

await once(server, "listening");

const client = new H2CClient(`http://localhost:${server.address().port}`);

client.on("connect", (origin) => {
console.log(`Connected to ${origin}`); // should print before the request body statement
});

try {
const { body } = await client.request({
path: "/",
method: "GET",
});
body.setEncoding("utf-8");
body.on("data", console.log);
client.close();
server.close();
} catch (error) {
console.error(error);
client.close();
server.close();
}
```

### Event: `'disconnect'`

See [Dispatcher Event: `'disconnect'`](/docs/docs/api/Dispatcher.md#event-disconnect).

Parameters:

- **origin** `URL`
- **targets** `Array<Dispatcher>`
- **error** `Error`

Emitted when socket has disconnected. The error argument of the event is the error which caused the socket to disconnect. The client will reconnect if or once `client.size > 0`.

#### Example - Client disconnect event

```js
import { createServer } from "node:http2";
import { H2CClient } from "undici";
import { once } from "events";

const server = createServer((request, response) => {
response.destroy();
}).listen();

await once(server, "listening");

const client = new H2CClient(`http://localhost:${server.address().port}`);

client.on("disconnect", (origin) => {
console.log(`Disconnected from ${origin}`);
});

try {
await client.request({
path: "/",
method: "GET",
});
} catch (error) {
console.error(error.message);
client.close();
server.close();
}
```

### Event: `'drain'`

Emitted when pipeline is no longer busy.

See [Dispatcher Event: `'drain'`](/docs/docs/api/Dispatcher.md#event-drain).

#### Example - Client drain event

```js
import { createServer } from "node:http2";
import { H2CClient } from "undici";
import { once } from "events";

const server = createServer((request, response) => {
response.end("Hello, World!");
}).listen();

await once(server, "listening");

const client = new H2CClient(`http://localhost:${server.address().port}`);

client.on("drain", () => {
console.log("drain event");
client.close();
server.close();
});

const requests = [
client.request({ path: "/", method: "GET" }),
client.request({ path: "/", method: "GET" }),
client.request({ path: "/", method: "GET" }),
];

await Promise.all(requests);

console.log("requests completed");
```

### Event: `'error'`

Invoked for users errors such as throwing in the `onError` handler.
4 changes: 3 additions & 1 deletion docs/docs/api/MockAgent.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,8 @@ Extends: [`AgentOptions`](/docs/docs/api/Agent.md#parameter-agentoptions)

* **ignoreTrailingSlash** `boolean` (optional) - Default: `false` - set the default value for `ignoreTrailingSlash` for interceptors.

* **acceptNonStandardSearchParameters** `boolean` (optional) - Default: `false` - set to `true` if the matcher should also accept non standard search parameters such as multi-value items specified with `[]` (e.g. `param[]=1&param[]=2&param[]=3`) and multi-value items which values are comma separated (e.g. `param=1,2,3`).

### Example - Basic MockAgent instantiation

This will instantiate the MockAgent. It will not do anything until registered as the agent to use with requests and mock interceptions are added.
@@ -477,7 +479,7 @@ This method returns any pending interceptors registered on a mock agent. A pendi

Returns: `PendingInterceptor[]` (where `PendingInterceptor` is a `MockDispatch` with an additional `origin: string`)

#### Example - List all pending inteceptors
#### Example - List all pending interceptors

```js
const agent = new MockAgent()
1 change: 1 addition & 0 deletions docs/docsify/sidebar.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
* API
* [Dispatcher](/docs/api/Dispatcher.md "Undici API - Dispatcher")
* [Client](/docs/api/Client.md "Undici API - Client")
* [H2CClient](/docs/api/H2CClient.md "Undici H2C API - Client")
* [Pool](/docs/api/Pool.md "Undici API - Pool")
* [BalancedPool](/docs/api/BalancedPool.md "Undici API - BalancedPool")
* [Agent](/docs/api/Agent.md "Undici API - Agent")
20 changes: 12 additions & 8 deletions docs/examples/README.md
Original file line number Diff line number Diff line change
@@ -126,17 +126,21 @@ async function deleteRequest (port = 3001) {
}
```

## Cacheable DNS Lookup
## Production configuration

### Using CacheableLookup to cache DNS lookups in undici
### Using interceptors to add response caching, DNS lookup caching and connection retries

```js
import { Agent } from 'undici'
import CacheableLookup from 'cacheable-lookup';
import { Agent, interceptors, setGlobalDispatcher } from 'undici'

const cacheable = new CacheableLookup(opts)
// Interceptors to add response caching, DNS caching and retrying to the dispatcher
const { cache, dns, retry } = interceptors

const agent = new Agent({
connect: { lookup: cacheable.lookup }
})
const defaultDispatcher = new Agent({
connections: 100, // Limit concurrent kept-alive connections to not run out of resources
headersTimeout: 10_000, // 10 seconds; set as appropriate for the remote servers you plan to connect to
bodyTimeout: 10_000,
}).compose(cache(), dns(), retry())

setGlobalDispatcher(defaultDispatcher) // Add these interceptors to all `fetch` and Undici `request` calls
```
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ const Agent = require('./lib/dispatcher/agent')
const ProxyAgent = require('./lib/dispatcher/proxy-agent')
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
const RetryAgent = require('./lib/dispatcher/retry-agent')
const H2CClient = require('./lib/dispatcher/h2c-client')
const errors = require('./lib/core/errors')
const util = require('./lib/core/util')
const { InvalidArgumentError } = errors
@@ -33,6 +34,7 @@ module.exports.Agent = Agent
module.exports.ProxyAgent = ProxyAgent
module.exports.EnvHttpProxyAgent = EnvHttpProxyAgent
module.exports.RetryAgent = RetryAgent
module.exports.H2CClient = H2CClient
module.exports.RetryHandler = RetryHandler

module.exports.DecoratorHandler = DecoratorHandler
Loading