Socket
Socket
Sign inDemoInstall

undici

Package Overview
Dependencies
Maintainers
3
Versions
212
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

undici - npm Package Compare versions

Comparing version 4.13.0 to 4.14.0

70

docs/api/MockPool.md

@@ -65,3 +65,3 @@ # Class: MockPool

* **reply** `(statusCode: number, replyData: string | Buffer | object, responseOptions?: MockResponseOptions) => MockScope` - define a reply for a matching request. Default for `responseOptions` is `{}`.
* **reply** `(statusCode: number, replyData: string | Buffer | object | MockInterceptor.MockResponseDataHandler, responseOptions?: MockResponseOptions) => MockScope` - define a reply for a matching request. You can define this as a callback to read incoming request data. Default for `responseOptions` is `{}`.
* **replyWithError** `(error: Error) => MockScope` - define an error for a matching request to throw.

@@ -117,2 +117,68 @@ * **defaultReplyHeaders** `(headers: Record<string, string>) => MockInterceptor` - define default headers to be included in subsequent replies. These are in addition to headers on a specific reply.

#### Example - Mocked request using reply data callbacks
```js
import { MockAgent, setGlobalDispatcher, request } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({
path: '/echo',
method: 'GET',
headers: {
'User-Agent': 'undici',
Host: 'example.com'
}
}).reply(200, ({ headers }) => ({ message: headers.get('message') }))
const { statusCode, body, headers } = await request('http://localhost:3000', {
headers: {
message: 'hello world!'
}
})
console.log('response received', statusCode) // response received 200
console.log('headers', headers) // { 'content-type': 'application/json' }
for await (const data of body) {
console.log('data', data.toString('utf8')) // { "message":"hello world!" }
}
```
#### Example - Mocked request using reply options callback
```js
import { MockAgent, setGlobalDispatcher, request } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({
path: '/echo',
method: 'GET',
headers: {
'User-Agent': 'undici',
Host: 'example.com'
}
}).reply(({ headers }) => ({ statusCode: 200, data: { message: headers.get('message') }})))
const { statusCode, body, headers } = await request('http://localhost:3000', {
headers: {
message: 'hello world!'
}
})
console.log('response received', statusCode) // response received 200
console.log('headers', headers) // { 'content-type': 'application/json' }
for await (const data of body) {
console.log('data', data.toString('utf8')) // { "message":"hello world!" }
}
```
#### Example - Basic Mocked requests with multiple intercepts

@@ -135,3 +201,3 @@

path: '/hello',
method: 'GET'
method: 'GET',
}).reply(200, 'hello')

@@ -138,0 +204,0 @@

2

index.d.ts

@@ -13,3 +13,3 @@ import Dispatcher = require('./types/dispatcher')

import mockErrors = require('./types/mock-errors')
import ProxyAgent from './types/proxy-agent'
import ProxyAgent = require('./types/proxy-agent')
import { request, pipeline, stream, connect, upgrade } from './types/api'

@@ -16,0 +16,0 @@

@@ -27,5 +27,2 @@ 'use strict'

const buildConnector = require('./core/connect')
const llhttpWasmData = require('./llhttp/llhttp.wasm.js')
const llhttpSimdWasmData = require('./llhttp/llhttp_simd.wasm.js')
const {

@@ -417,3 +414,3 @@ kUrl,

try {
mod = await WebAssembly.compile(Buffer.from(llhttpWasmData, 'base64'))
mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp_simd.wasm.js'), 'base64'))
} catch (e) {

@@ -426,3 +423,3 @@ /* istanbul ignore next */

// got me to remove that check to avoid breaking Node 12.
mod = await WebAssembly.compile(Buffer.from(llhttpSimdWasmData, 'base64'))
mod = await WebAssembly.compile(Buffer.from(require('./llhttp/llhttp.wasm.js'), 'base64'))
}

@@ -429,0 +426,0 @@

'use strict'
const net = require('net')
const tls = require('tls')
const assert = require('assert')
const util = require('./util')
const { InvalidArgumentError, ConnectTimeoutError } = require('./errors')
let tls // include tls conditionally since it is not always available

@@ -27,2 +27,5 @@ // TODO: session re-use does not wait for the first

if (protocol === 'https:') {
if (!tls) {
tls = require('tls')
}
servername = servername || options.servername || util.getServerName(host) || null

@@ -29,0 +32,0 @@

@@ -127,2 +127,6 @@ 'use strict'

stream (...args) {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return this[kState].blobLike.stream(...args)

@@ -132,2 +136,6 @@ }

arrayBuffer (...args) {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return this[kState].blobLike.arrayBuffer(...args)

@@ -137,2 +145,6 @@ }

slice (...args) {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return this[kState].blobLike.slice(...args)

@@ -142,2 +154,6 @@ }

text (...args) {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return this[kState].blobLike.text(...args)

@@ -147,2 +163,6 @@ }

get size () {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return this[kState].blobLike.size

@@ -152,2 +172,6 @@ }

get type () {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return this[kState].blobLike.type

@@ -173,2 +197,6 @@ }

get [Symbol.toStringTag] () {
if (!(this instanceof FileLike)) {
throw new TypeError('Illegal invocation')
}
return 'File'

@@ -175,0 +203,0 @@ }

@@ -143,3 +143,3 @@ /* globals AbortController */

// undici implementation note: this is set as the first item in request's urlList in makeRequest
// method request’s method.
// method request’s method.
method: request.method,

@@ -149,3 +149,3 @@ // header list A copy of request’s header list.

headersList: request.headersList,
// unsafe-request flag Set.
// unsafe-request flag Set.
unsafeRequest: request.unsafeRequest,

@@ -156,14 +156,14 @@ // client This’s relevant settings object.

window,
// priority request’s priority.
// priority request’s priority.
priority: request.priority,
// origin request’s origin. The propagation of the origin is only significant for navigation requests
// being handled by a service worker. In this scenario a request can have an origin that is different
// being handled by a service worker. In this scenario a request can have an origin that is different
// from the current client.
origin: request.origin,
// referrer request’s referrer.
referrer: request.referrer,
referrer: request.referrer,
// referrer policy request’s referrer policy.
referrerPolicy: request.referrerPolicy,
// mode request’s mode.
mode: request.mode,
mode: request.mode,
// credentials mode request’s credentials mode.

@@ -174,3 +174,3 @@ credentials: request.credentials,

// redirect mode request’s redirect mode.
redirect: request.redirect,
redirect: request.redirect,
// integrity metadata request’s integrity metadata.

@@ -327,3 +327,3 @@ integrity: request.integrity,

// 23. If init["integrity"] exists, then set request’s integrity metadata to it.
if ('integrity' in init) {
if ('integrity' in init && init.integrity != null) {
request.integrity = String(init.integrity)

@@ -330,0 +330,0 @@ }

@@ -64,3 +64,3 @@ 'use strict'

// then return blocked.
if (/^http?s/.test(url.protocol) && badPorts.includes(url.port)) {
if (/^https?:/.test(url.protocol) && badPorts.includes(url.port)) {
return 'blocked'

@@ -67,0 +67,0 @@ }

@@ -12,3 +12,3 @@ 'use strict'

} = require('./mock-symbols')
const { InvalidArgumentError } = require('../core/errors')
const { InvalidArgumentError, InvalidReturnValueError } = require('../core/errors')

@@ -78,6 +78,12 @@ /**

/**
* Mock an undici request with a defined reply.
*/
reply (statusCode, data, responseOptions = {}) {
createMockScopeDispatchData(statusCode, data, responseOptions = {}) {
const responseData = getResponseData(data)
const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {}
const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers }
const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers }
return { statusCode, data, headers, trailers };
}
validateReplyParameters(statusCode, data, responseOptions) {
if (typeof statusCode === 'undefined') {

@@ -92,9 +98,49 @@ throw new InvalidArgumentError('statusCode must be defined')

}
}
const responseData = getResponseData(data)
const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {}
const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers }
const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers }
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { statusCode, data, headers, trailers })
/**
* Mock an undici request with a defined reply.
*/
reply (replyData) {
// Values of reply aren't available right now as they
// can only be available when the reply callback is invoked.
if (typeof replyData === 'function') {
// We'll first wrap the provided callback in another function,
// this function will properly resolve the data from the callback
// when invoked.
const wrappedDefaultsCallback = (opts) => {
// Our reply options callback contains the parameter for statusCode, data and options.
const resolvedData = replyData(opts);
// Check if it is in the right format
if (typeof resolvedData !== 'object') {
throw new InvalidArgumentError('reply options callback must return an object')
}
const { statusCode, data, responseOptions = {}} = resolvedData;
this.validateReplyParameters(statusCode, data, responseOptions);
// Since the values can be obtained immediately we return them
// from this higher order function that will be resolved later.
return {
...this.createMockScopeDispatchData(statusCode, data, responseOptions)
}
}
// Add usual dispatch data, but this time set the data parameter to function that will eventually provide data.
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback)
return new MockScope(newMockDispatch);
}
// We can have either one or three parameters, if we get here,
// we should have 2-3 parameters. So we spread the arguments of
// this function to obtain the parameters, since replyData will always
// just be the statusCode.
const [statusCode, data, responseOptions = {}] = [...arguments];
this.validateReplyParameters(statusCode, data, responseOptions);
// Send in-already provided data like usual
const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions);
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData)
return new MockScope(newMockDispatch)
}

@@ -101,0 +147,0 @@

@@ -93,3 +93,4 @@ 'use strict'

const baseData = { times: null, persist: false, consumed: false }
const newMockDispatch = { ...baseData, ...key, data: { error: null, ...data } }
const replyData = typeof data === 'function' ? { callback: data } : { ...data };
const newMockDispatch = { ...baseData, ...key, data: { error: null, ...replyData } }
mockDispatches.push(newMockDispatch)

@@ -139,4 +140,9 @@ return newMockDispatch

const key = buildKey(opts)
const mockDispatch = getMockDispatch(this[kDispatches], key)
let mockDispatch = getMockDispatch(this[kDispatches], key)
// Here's where we resolve a callback if a callback is present for the dispatch data.
if (mockDispatch.data.callback) {
mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) }
}
// Parse mockDispatch data

@@ -174,3 +180,3 @@ const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch

function handleReply (mockDispatches) {
const responseData = getResponseData(data)
const responseData = getResponseData(typeof data === 'function' ? data(opts) : data);
const responseHeaders = generateKeyValues(headers)

@@ -177,0 +183,0 @@ const responseTrailers = generateKeyValues(trailers)

{
"name": "undici",
"version": "4.13.0",
"version": "4.14.0",
"description": "An HTTP/1.1 client, written from scratch for Node.js",

@@ -49,4 +49,4 @@ "homepage": "https://undici.nodejs.org",

"test": "npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:jest && tsd",
"test:node-fetch": "node scripts/verifyVersion.js 16 && mocha test/node-fetch || echo Skipping",
"test:fetch": "node scripts/verifyVersion.js 16 && tap test/fetch/*.js || echo Skipping",
"test:node-fetch": "node scripts/verifyVersion.js 16 || mocha test/node-fetch",
"test:fetch": "node scripts/verifyVersion.js 16 || tap test/fetch/*.js",
"test:jest": "jest test/jest/test",

@@ -53,0 +53,0 @@ "test:tap": "tap test/*.js test/diagnostics-channel/*.js",

@@ -167,3 +167,5 @@ # undici

This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard. We plan to ship breaking changes to this feature until it is out of experimental.
This is [experimental](https://nodejs.org/api/documentation.html#documentation_stability_index) and is not yet fully compliant with the Fetch Standard.
We plan to ship breaking changes to this feature until it is out of experimental.
Help us improve the test coverage by following instructions at [nodejs/undici/#951](https://github.com/nodejs/undici/issues/951).

@@ -182,2 +184,33 @@ Basic usage example:

#### `request.body`
A body can be of the following types:
- ArrayBuffer
- ArrayBufferView
- AsyncIterables
- Blob
- Iterables
- String
- URLSearchParams
- FormData
In this implementation of fetch, ```request.body ``` now accepts ```Async Iterables```. It is not present in the [Fetch Standard.](https://fetch.spec.whatwg.org)
```js
import { fetch } from "undici";
const data = {
async *[Symbol.asyncIterator]() {
yield "hello";
yield "world";
},
};
(async () => {
await fetch("https://example.com", { body: data, method: 'POST' });
})();
```
#### `response.body`

@@ -304,2 +337,11 @@

### Manual Redirect
Since it is not possible to manually follow an HTTP redirect on server-side,
Undici returns the actual response instead of an `opaqueredirect` filtered one
when invoked with a `manual` redirect. This aligns `fetch()` with the other
implementations in Deno and Cloudflare Workers.
Refs: https://fetch.spec.whatwg.org/#atomic-http-redirect-handling
## Collaborators

@@ -306,0 +348,0 @@

@@ -16,3 +16,3 @@ import { URL, UrlObject } from 'url'

url: string | URL | UrlObject,
options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions, 'origin' | 'path'>,
options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions, 'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>,
): Promise<Dispatcher.ResponseData>;

@@ -19,0 +19,0 @@

@@ -45,3 +45,3 @@ // based on https://github.com/Ethan-Arrowood/undici-fetch/blob/249269714db874351589d2d364a0645d5160ae71/index.d.ts (MIT license)

export type HeadersInit = Iterable<[string, string]> | Record<string, string>
export type HeadersInit = string[][] | Record<string, string> | Headers

@@ -104,4 +104,20 @@ export declare class Headers implements Iterable<[string, string]> {

readonly signal?: AbortSignal
readonly credentials?: RequestCredentials
readonly mode?: RequestMode
readonly referrer?: string
readonly referrerPolicy?: ReferrerPolicy
readonly window?: null
}
export type ReferrerPolicy =
| ''
| 'no-referrer'
| 'no-referrer-when-downgrade'
| 'origin'
| 'origin-when-cross-origin'
| 'same-origin'
| 'strict-origin'
| 'strict-origin-when-cross-origin'
| 'unsafe-url';
export type RequestMode = 'cors' | 'navigate' | 'no-cors' | 'same-origin'

@@ -108,0 +124,0 @@

import { IncomingHttpHeaders } from 'http'
import Dispatcher from './dispatcher';

@@ -24,3 +25,8 @@ export {

/** Mock an undici request with the defined reply. */
reply<TData extends object = object>(statusCode: number, data: TData | Buffer| string , responseOptions?: MockInterceptor.MockResponseOptions): MockScope<TData>;
reply<TData extends object = object>(replyOptionsCallback: MockInterceptor.MockReplyOptionsCallback<TData>): MockScope<TData>;
reply<TData extends object = object>(
statusCode: number,
data: TData | Buffer | string | MockInterceptor.MockResponseDataHandler<TData>,
responseOptions?: MockInterceptor.MockResponseOptions
): MockScope<TData>;
/** Mock an undici request by throwing the defined reply error. */

@@ -63,7 +69,24 @@ replyWithError<TError extends Error = Error>(error: TError): MockScope;

}
export interface MockResponseCallbackOptions {
path: string;
origin: string;
method: string;
body?: string;
headers: Headers;
maxRedirections: number;
}
export type MockResponseDataHandler<TData extends object = object> = (
opts: MockResponseCallbackOptions
) => TData | Buffer | string;
export type MockReplyOptionsCallback<TData extends object = object> = (
opts: MockResponseCallbackOptions
) => { statusCode: number, data: TData | Buffer | string, responseOptions?: MockResponseOptions }
}
interface Interceptable {
interface Interceptable extends Dispatcher {
/** Intercepts any matching requests that use the same origin as this mock client. */
intercept(options: MockInterceptor.Options): MockInterceptor;
}

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc