CoolFace
Apppublic

opusdev/vector-similarity-api

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes
README.md474 linesDownload Raw Back to undici
1# undici2 3[![Node CI](https://github.com/nodejs/undici/actions/workflows/nodejs.yml/badge.svg)](https://github.com/nodejs/undici/actions/workflows/nodejs.yml) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/) [![npm version](https://badge.fury.io/js/undici.svg)](https://badge.fury.io/js/undici) [![codecov](https://codecov.io/gh/nodejs/undici/branch/main/graph/badge.svg?token=yZL6LtXkOA)](https://codecov.io/gh/nodejs/undici)4 5An HTTP/1.1 client, written from scratch for Node.js.6 7> Undici means eleven in Italian. 1.1 -> 11 -> Eleven -> Undici.8It is also a Stranger Things reference.9 10## How to get involved11 12Have a question about using Undici? Open a [Q&A Discussion](https://github.com/nodejs/undici/discussions/new) or join our official OpenJS [Slack](https://openjs-foundation.slack.com/archives/C01QF9Q31QD) channel.13 14Looking to contribute? Start by reading the [contributing guide](./CONTRIBUTING.md)15 16## Install17 18```19npm i undici20```21 22## Benchmarks23 24The benchmark is a simple getting data [example](https://github.com/nodejs/undici/blob/main/benchmarks/benchmark.js) using a2550 TCP connections with a pipelining depth of 10 running on Node 20.10.0.26 27|       _Tests_       | _Samples_ |     _Result_     | _Tolerance_ | _Difference with slowest_ |28| :-----------------: | :-------: | :--------------: | :---------: | :-----------------------: |29|   undici - fetch    |    30     | 3704.43 req/sec  |  ± 2.95 %   |             -             |30| http - no keepalive |    20     | 4275.30 req/sec  |  ± 2.60 %   |         + 15.41 %         |31|     node-fetch      |    10     | 4759.42 req/sec  |  ± 0.87 %   |         + 28.48 %         |32|       request       |    40     | 4803.37 req/sec  |  ± 2.77 %   |         + 29.67 %         |33|        axios        |    45     | 4951.97 req/sec  |  ± 2.88 %   |         + 33.68 %         |34|         got         |    10     | 5969.67 req/sec  |  ± 2.64 %   |         + 61.15 %         |35|     superagent      |    10     | 9471.48 req/sec  |  ± 1.50 %   |        + 155.68 %         |36|  http - keepalive   |    25     | 10327.49 req/sec |  ± 2.95 %   |        + 178.79 %         |37|  undici - pipeline  |    10     | 15053.41 req/sec |  ± 1.63 %   |        + 306.36 %         |38|  undici - request   |    10     | 19264.24 req/sec |  ± 1.74 %   |        + 420.03 %         |39|   undici - stream   |    15     | 20317.29 req/sec |  ± 2.13 %   |        + 448.46 %         |40|  undici - dispatch  |    10     | 24883.28 req/sec |  ± 1.54 %   |        + 571.72 %         |41 42The benchmark is a simple sending data [example](https://github.com/nodejs/undici/blob/main/benchmarks/post-benchmark.js) using a4350 TCP connections with a pipelining depth of 10 running on Node 20.10.0.44 45|       _Tests_       | _Samples_ |    _Result_     | _Tolerance_ | _Difference with slowest_ |46| :-----------------: | :-------: | :-------------: | :---------: | :-----------------------: |47|   undici - fetch    |    20     | 1968.42 req/sec |  ± 2.63 %   |             -             |48| http - no keepalive |    25     | 2330.30 req/sec |  ± 2.99 %   |         + 18.38 %         |49|     node-fetch      |    20     | 2485.36 req/sec |  ± 2.70 %   |         + 26.26 %         |50|         got         |    15     | 2787.68 req/sec |  ± 2.56 %   |         + 41.62 %         |51|       request       |    30     | 2805.10 req/sec |  ± 2.59 %   |         + 42.50 %         |52|        axios        |    10     | 3040.45 req/sec |  ± 1.72 %   |         + 54.46 %         |53|     superagent      |    20     | 3358.29 req/sec |  ± 2.51 %   |         + 70.61 %         |54|  http - keepalive   |    20     | 3477.94 req/sec |  ± 2.51 %   |         + 76.69 %         |55|  undici - pipeline  |    25     | 3812.61 req/sec |  ± 2.80 %   |         + 93.69 %         |56|  undici - request   |    10     | 6067.00 req/sec |  ± 0.94 %   |        + 208.22 %         |57|   undici - stream   |    10     | 6391.61 req/sec |  ± 1.98 %   |        + 224.71 %         |58|  undici - dispatch  |    10     | 6397.00 req/sec |  ± 1.48 %   |        + 224.98 %         |59 60 61## Quick Start62 63```js64import { request } from 'undici'65 66const {67  statusCode,68  headers,69  trailers,70  body71} = await request('http://localhost:3000/foo')72 73console.log('response received', statusCode)74console.log('headers', headers)75 76for await (const data of body) { console.log('data', data) }77 78console.log('trailers', trailers)79```80 81## Body Mixins82 83The `body` mixins are the most common way to format the request/response body. Mixins include:84 85- [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer)86- [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob)87- [`.bytes()`](https://fetch.spec.whatwg.org/#dom-body-bytes)88- [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)89- [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)90 91> [!NOTE]92> The body returned from `undici.request` does not implement `.formData()`.93 94Example usage:95 96```js97import { request } from 'undici'98 99const {100  statusCode,101  headers,102  trailers,103  body104} = await request('http://localhost:3000/foo')105 106console.log('response received', statusCode)107console.log('headers', headers)108console.log('data', await body.json())109console.log('trailers', trailers)110```111 112_Note: Once a mixin has been called then the body cannot be reused, thus calling additional mixins on `.body`, e.g. `.body.json(); .body.text()` will result in an error `TypeError: unusable` being thrown and returned through the `Promise` rejection._113 114Should you need to access the `body` in plain-text after using a mixin, the best practice is to use the `.text()` mixin first and then manually parse the text to the desired format.115 116For more information about their behavior, please reference the body mixin from the [Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).117 118## Common API Methods119 120This section documents our most commonly used API methods. Additional APIs are documented in their own files within the [docs](./docs/) folder and are accessible via the navigation list on the left side of the docs site.121 122### `undici.request([url, options]): Promise`123 124Arguments:125 126* **url** `string | URL | UrlObject`127* **options** [`RequestOptions`](./docs/docs/api/Dispatcher.md#parameter-requestoptions)128  * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)129  * **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`130  * **maxRedirections** `Integer` - Default: `0`131 132Returns a promise with the result of the `Dispatcher.request` method.133 134Calls `options.dispatcher.request(options)`.135 136See [Dispatcher.request](./docs/docs/api/Dispatcher.md#dispatcherrequestoptions-callback) for more details, and [request examples](./examples/README.md) for examples.137 138### `undici.stream([url, options, ]factory): Promise`139 140Arguments:141 142* **url** `string | URL | UrlObject`143* **options** [`StreamOptions`](./docs/docs/api/Dispatcher.md#parameter-streamoptions)144  * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)145  * **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`146  * **maxRedirections** `Integer` - Default: `0`147* **factory** `Dispatcher.stream.factory`148 149Returns a promise with the result of the `Dispatcher.stream` method.150 151Calls `options.dispatcher.stream(options, factory)`.152 153See [Dispatcher.stream](./docs/docs/api/Dispatcher.md#dispatcherstreamoptions-factory-callback) for more details.154 155### `undici.pipeline([url, options, ]handler): Duplex`156 157Arguments:158 159* **url** `string | URL | UrlObject`160* **options** [`PipelineOptions`](./docs/docs/api/Dispatcher.md#parameter-pipelineoptions)161  * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)162  * **method** `String` - Default: `PUT` if `options.body`, otherwise `GET`163  * **maxRedirections** `Integer` - Default: `0`164* **handler** `Dispatcher.pipeline.handler`165 166Returns: `stream.Duplex`167 168Calls `options.dispatch.pipeline(options, handler)`.169 170See [Dispatcher.pipeline](./docs/docs/api/Dispatcher.md#dispatcherpipelineoptions-handler) for more details.171 172### `undici.connect([url, options]): Promise`173 174Starts two-way communications with the requested resource using [HTTP CONNECT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT).175 176Arguments:177 178* **url** `string | URL | UrlObject`179* **options** [`ConnectOptions`](./docs/docs/api/Dispatcher.md#parameter-connectoptions)180  * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)181  * **maxRedirections** `Integer` - Default: `0`182* **callback** `(err: Error | null, data: ConnectData | null) => void` (optional)183 184Returns a promise with the result of the `Dispatcher.connect` method.185 186Calls `options.dispatch.connect(options)`.187 188See [Dispatcher.connect](./docs/docs/api/Dispatcher.md#dispatcherconnectoptions-callback) for more details.189 190### `undici.fetch(input[, init]): Promise`191 192Implements [fetch](https://fetch.spec.whatwg.org/#fetch-method).193 194* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch195* https://fetch.spec.whatwg.org/#fetch-method196 197Basic usage example:198 199```js200import { fetch } from 'undici'201 202 203const res = await fetch('https://example.com')204const json = await res.json()205console.log(json)206```207 208You can pass an optional dispatcher to `fetch` as:209 210```js211import { fetch, Agent } from 'undici'212 213const res = await fetch('https://example.com', {214  // Mocks are also supported215  dispatcher: new Agent({216    keepAliveTimeout: 10,217    keepAliveMaxTimeout: 10218  })219})220const json = await res.json()221console.log(json)222```223 224#### `request.body`225 226A body can be of the following types:227 228- ArrayBuffer229- ArrayBufferView230- AsyncIterables231- Blob232- Iterables233- String234- URLSearchParams235- FormData236 237In this implementation of fetch, ```request.body``` now accepts ```Async Iterables```. It is not present in the [Fetch Standard.](https://fetch.spec.whatwg.org)238 239```js240import { fetch } from 'undici'241 242const data = {243  async *[Symbol.asyncIterator]() {244    yield 'hello'245    yield 'world'246  },247}248 249await fetch('https://example.com', { body: data, method: 'POST', duplex: 'half' })250```251 252[FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) besides text data and buffers can also utilize streams via [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects:253 254```js255import { openAsBlob } from 'node:fs'256 257const file = await openAsBlob('./big.csv')258const body = new FormData()259body.set('file', file, 'big.csv')260 261await fetch('http://example.com', { method: 'POST', body })262```263 264#### `request.duplex`265 266- half267 268In this implementation of fetch, `request.duplex` must be set if `request.body` is `ReadableStream` or `Async Iterables`, however, fetch requests are currently always full duplex. For more detail refer to the [Fetch Standard.](https://fetch.spec.whatwg.org/#dom-requestinit-duplex).269 270#### `response.body`271 272Nodejs has two kinds of streams: [web streams](https://nodejs.org/dist/latest-v16.x/docs/api/webstreams.html), which follow the API of the WHATWG web standard found in browsers, and an older Node-specific [streams API](https://nodejs.org/api/stream.html). `response.body` returns a readable web stream. If you would prefer to work with a Node stream you can convert a web stream using `.fromWeb()`.273 274```js275import { fetch } from 'undici'276import { Readable } from 'node:stream'277 278const response = await fetch('https://example.com')279const readableWebStream = response.body280const readableNodeStream = Readable.fromWeb(readableWebStream)281```282 283#### Specification Compliance284 285This section documents parts of the [Fetch Standard](https://fetch.spec.whatwg.org) that Undici does286not support or does not fully implement.287 288##### Garbage Collection289 290* https://fetch.spec.whatwg.org/#garbage-collection291 292The [Fetch Standard](https://fetch.spec.whatwg.org) allows users to skip consuming the response body by relying on293[garbage collection](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#garbage_collection) to release connection resources. Undici does not do the same. Therefore, it is important to always either consume or cancel the response body.294 295Garbage collection in Node is less aggressive and deterministic296(due to the lack of clear idle periods that browsers have through the rendering refresh rate)297which means that leaving the release of connection resources to the garbage collector can lead298to excessive connection usage, reduced performance (due to less connection re-use), and even299stalls or deadlocks when running out of connections.300 301```js302// Do303const headers = await fetch(url)304  .then(async res => {305    for await (const chunk of res.body) {306      // force consumption of body307    }308    return res.headers309  })310 311// Do not312const headers = await fetch(url)313  .then(res => res.headers)314```315 316However, if you want to get only headers, it might be better to use `HEAD` request method. Usage of this method will obviate the need for consumption or cancelling of the response body. See [MDN - HTTP - HTTP request methods - HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) for more details.317 318```js319const headers = await fetch(url, { method: 'HEAD' })320  .then(res => res.headers)321```322 323##### Forbidden and Safelisted Header Names324 325* https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name326* https://fetch.spec.whatwg.org/#forbidden-header-name327* https://fetch.spec.whatwg.org/#forbidden-response-header-name328* https://github.com/wintercg/fetch/issues/6329 330The [Fetch Standard](https://fetch.spec.whatwg.org) requires implementations to exclude certain headers from requests and responses. In browser environments, some headers are forbidden so the user agent remains in full control over them. In Undici, these constraints are removed to give more control to the user.331 332#### Content-Encoding333 334* https://www.rfc-editor.org/rfc/rfc9110#field.content-encoding335 336Undici limits the number of `Content-Encoding` layers in a response to **5** to prevent resource exhaustion attacks. If a server responds with more than 5 content-encodings (e.g., `Content-Encoding: gzip, gzip, gzip, gzip, gzip, gzip`), the fetch will be rejected with an error. This limit matches the approach taken by [curl](https://curl.se/docs/CVE-2022-32206.html) and [urllib3](https://github.com/advisories/GHSA-gm62-xv2j-4rw9).337 338#### `undici.upgrade([url, options]): Promise`339 340Upgrade to a different protocol. See [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.341 342Arguments:343 344* **url** `string | URL | UrlObject`345* **options** [`UpgradeOptions`](./docs/docs/api/Dispatcher.md#parameter-upgradeoptions)346  * **dispatcher** `Dispatcher` - Default: [getGlobalDispatcher](#undicigetglobaldispatcher)347  * **maxRedirections** `Integer` - Default: `0`348* **callback** `(error: Error | null, data: UpgradeData) => void` (optional)349 350Returns a promise with the result of the `Dispatcher.upgrade` method.351 352Calls `options.dispatcher.upgrade(options)`.353 354See [Dispatcher.upgrade](./docs/docs/api/Dispatcher.md#dispatcherupgradeoptions-callback) for more details.355 356### `undici.setGlobalDispatcher(dispatcher)`357 358* dispatcher `Dispatcher`359 360Sets the global dispatcher used by Common API Methods.361 362### `undici.getGlobalDispatcher()`363 364Gets the global dispatcher used by Common API Methods.365 366Returns: `Dispatcher`367 368### `undici.setGlobalOrigin(origin)`369 370* origin `string | URL | undefined`371 372Sets the global origin used in `fetch`.373 374If `undefined` is passed, the global origin will be reset. This will cause `Response.redirect`, `new Request()`, and `fetch` to throw an error when a relative path is passed.375 376```js377setGlobalOrigin('http://localhost:3000')378 379const response = await fetch('/api/ping')380 381console.log(response.url) // http://localhost:3000/api/ping382```383 384### `undici.getGlobalOrigin()`385 386Gets the global origin used in `fetch`.387 388Returns: `URL`389 390### `UrlObject`391 392* **port** `string | number` (optional)393* **path** `string` (optional)394* **pathname** `string` (optional)395* **hostname** `string` (optional)396* **origin** `string` (optional)397* **protocol** `string` (optional)398* **search** `string` (optional)399 400## Specification Compliance401 402This section documents parts of the HTTP/1.1 specification that Undici does403not support or does not fully implement.404 405### Expect406 407Undici does not support the `Expect` request header field. The request408body is  always immediately sent and the `100 Continue` response will be409ignored.410 411Refs: https://tools.ietf.org/html/rfc7231#section-5.1.1412 413### Pipelining414 415Undici will only use pipelining if configured with a `pipelining` factor416greater than `1`.417 418Undici always assumes that connections are persistent and will immediately419pipeline requests, without checking whether the connection is persistent.420Hence, automatic fallback to HTTP/1.0 or HTTP/1.1 without pipelining is421not supported.422 423Undici will immediately pipeline when retrying requests after a failed424connection. However, Undici will not retry the first remaining requests in425the prior pipeline and instead error the corresponding callback/promise/stream.426 427Undici will abort all running requests in the pipeline when any of them are428aborted.429 430* Refs: https://tools.ietf.org/html/rfc2616#section-8.1.2.2431* Refs: https://tools.ietf.org/html/rfc7230#section-6.3.2432 433### Manual Redirect434 435Since it is not possible to manually follow an HTTP redirect on the server-side,436Undici returns the actual response instead of an `opaqueredirect` filtered one437when invoked with a `manual` redirect. This aligns `fetch()` with the other438implementations in Deno and Cloudflare Workers.439 440Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling441 442## Workarounds443 444### Network address family autoselection.445 446If you experience problem when connecting to a remote server that is resolved by your DNS servers to a IPv6 (AAAA record)447first, there are chances that your local router or ISP might have problem connecting to IPv6 networks. In that case448undici will throw an error with code `UND_ERR_CONNECT_TIMEOUT`.449 450If the target server resolves to both a IPv6 and IPv4 (A records) address and you are using a compatible Node version451(18.3.0 and above), you can fix the problem by providing the `autoSelectFamily` option (support by both `undici.request`452and `undici.Agent`) which will enable the family autoselection algorithm when establishing the connection.453 454## Collaborators455 456* [__Daniele Belardi__](https://github.com/dnlup), <https://www.npmjs.com/~dnlup>457* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>458* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>459* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>460* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>461* [__Szymon Marczak__](https://github.com/szmarczak), <https://www.npmjs.com/~szmarczak>462* [__Tomas Della Vedova__](https://github.com/delvedor), <https://www.npmjs.com/~delvedor>463 464### Releasers465 466* [__Ethan Arrowood__](https://github.com/ethan-arrowood), <https://www.npmjs.com/~ethan_arrowood>467* [__Matteo Collina__](https://github.com/mcollina), <https://www.npmjs.com/~matteo.collina>468* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>469* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>470 471## License472 473MIT474