This commit is contained in:
2026-03-03 15:23:00 +00:00
parent 5e3726de39
commit 8e223bfbec
3689 changed files with 955330 additions and 1011 deletions

11
node_modules/@hapi/wreck/LICENSE.md generated vendored Executable file
View File

@@ -0,0 +1,11 @@
Copyright (c) 2012-2022, Project contributors
Copyright (c) 2012-2020, Sideway Inc
Copyright (c) 2012-2014, Walmart.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

17
node_modules/@hapi/wreck/README.md generated vendored Executable file
View File

@@ -0,0 +1,17 @@
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
# @hapi/wreck
#### HTTP client utilities.
**wreck** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) they work even better together.
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
## Useful resources
- [Documentation and API](https://hapi.dev/family/wreck/)
- [Versions status](https://hapi.dev/resources/status/#wreck) (builds, dependencies, node versions, licenses, eol)
- [Changelog](https://hapi.dev/family/wreck/changelog/)
- [Project policies](https://hapi.dev/policies/)
- [Free and commercial support options](https://hapi.dev/support/)

366
node_modules/@hapi/wreck/lib/index.d.ts generated vendored Executable file
View File

@@ -0,0 +1,366 @@
/// <reference types="node" />
import { EventEmitter } from 'events';
import * as Http from 'http';
import * as Https from 'https';
import * as Stream from 'stream';
import * as Url from 'url';
import { LookupFunction } from "node:net"
import { Boom } from '@hapi/boom';
/**
* An HTTP request client.
*/
declare class Client {
/**
* An object containing the node agents used for pooling connections for `http` and `https`.
*/
agents: Client.Agents;
/**
* An event emitter used to deliver events when the `events` option is set.
*/
events?: Client.Events;
/**
* Creates a new client.
*
* @param options - the client default options.
*/
constructor(options?: Client.Options);
/**
* Creates a new client using the current client options as defaults and the provided options as override.
*
* @param options - the client override options.
*
* @returns a new client.
*/
defaults(options: Client.Options): Client;
/**
* Request an HTTP resource.
*
* @param method - a string specifying the HTTP request method. Defaults to 'GET'.
* @param url - the URI of the requested resource.
* @param options - default options override.
*
* @returns a promise resolving into an HTTP response object with a 'req' property holding a reference to the HTTP request object.
*/
request(method: string, url: string, options?: Client.request.Options): Promise<Http.IncomingMessage> & { req: Http.ClientRequest };
/**
* Reads a readable stream and returns the parsed payload.
*
* @param res - the readable stream.
* @param options - default options override.
*
* @returns the parsed payload based on the provided options.
*/
read<T = Buffer>(res: Stream.Readable | Http.IncomingMessage, options?: Client.read.Options): Promise<T>;
/**
* Converts a buffer, string, or an array of them into a readable stream.
*
* @param payload - a string, buffer, or an array of them.
* @param encoding - the payload encoding.
*
* @returns a readable stream.
*/
toReadableStream(payload: Client.toReadableStream.Payload, encoding?: string): Stream.Readable;
/**
* Parses the HTTP Cache-Control header.
*
* @param field - the header content.
*
* @returns an object with the header parameters or null if invalid.
*/
parseCacheControl(field: string): Client.parseCacheControl.Parameters | null;
/**
* Performs an HTTP GET request.
*
* @param uri - the resource URI.
* @param options - default options override.
*
* @returns the received payload Buffer or parsed payload based on the options.
*/
get<T>(uri: string, options?: Client.request.Options & Client.read.Options): Promise<Client.request.Response<T>>;
/**
* Performs an HTTP POST request.
*
* @param uri - the resource URI.
* @param options - default options override.
*
* @returns the received payload Buffer or parsed payload based on the options.
*/
post<T>(uri: string, options?: Client.request.Options & Client.read.Options): Promise<Client.request.Response<T>>;
/**
* Performs an HTTP PATCH request.
*
* @param uri - the resource URI.
* @param options - default options override.
*
* @returns the received payload Buffer or parsed payload based on the options.
*/
patch<T>(uri: string, options?: Client.request.Options & Client.read.Options): Promise<Client.request.Response<T>>;
/**
* Performs an HTTP PUT request.
*
* @param uri - the resource URI.
* @param options - default options override.
*
* @returns the received payload Buffer or parsed payload based on the options.
*/
put<T>(uri: string, options?: Client.request.Options & Client.read.Options): Promise<Client.request.Response<T>>;
/**
* Performs an HTTP DELETE request.
*
* @param uri - the resource URI.
* @param options - default options override.
*
* @returns the received payload Buffer or parsed payload based on the options.
*/
delete<T>(uri: string, options?: Client.request.Options & Client.read.Options): Promise<Client.request.Response<T>>;
}
declare namespace Client {
interface Options extends request.Options, read.Options {
/**
* An object containing the node agents used for pooling connections for `http` and `https`.
*/
readonly agents?: Agents;
/**
* Enables events.
*
* @default false
*/
readonly events?: boolean;
}
interface Agents {
/**
* The agent used for HTTP requests.
*/
readonly http: Http.Agent;
/**
* The agent used for HTTPS requests.
*/
readonly https: Https.Agent;
/**
* The agent used for HTTPS requests which ignores unauthorized requests.
*/
readonly httpsAllowUnauthorized: Https.Agent;
}
class Events extends EventEmitter {
on(event: 'preRequest', litener: Events.preRequest): this;
once(event: 'preRequest', litener: Events.preRequest): this;
addListener(event: 'preRequest', litener: Events.preRequest): this;
on(event: 'request', listener: Events.request): this;
once(event: 'request', listener: Events.request): this;
addListener(event: 'request', listener: Events.request): this;
on(event: 'response', listener: Events.response): this;
once(event: 'response', listener: Events.response): this;
addListener(event: 'response', listener: Events.response): this;
}
namespace Events {
type preRequest = (uri: string, options: Client.Options) => void;
type request = (req: Http.ClientRequest) => void;
type response = (err: Boom | undefined, details: { req: Http.ClientRequest, res: Http.IncomingMessage | undefined, start: number, url: Url.URL }) => void;
}
namespace request {
interface Options {
/**
* Node HTTP or HTTPS Agent object (false disables agent pooling).
*/
readonly agent?: Http.Agent | Https.Agent | false;
/**
* Custom lookup function. Default: dns.lookup().
*/
readonly lookup?: LookupFunction;
/**
* IP address family to use when resolving host or hostname. Valid values are 4 or 6. When unspecified, both IP v4 and v6 will be used.
*/
readonly family?: number;
/**
* Optional dns.lookup() hints.
*/
readonly hints?: number;
/**
* Fully qualified URL string used as the base URL.
*/
readonly baseUrl?: string;
/**
* A function to call before a redirect is triggered.
*
* @param redirectMethod - a string specifying the redirect method.
* @param statusCode - HTTP status code of the response that triggered the redirect.
* @param location - The redirect location string.
* @param resHeaders - An object with the headers received as part of the redirection response.
* @param redirectOptions - Options that will be applied to the redirect request. Changes to this object are applied to the redirection request.
* @param next - the callback function called to perform the redirection.
*/
readonly beforeRedirect?: (redirectMethod: string, statusCode: number, location: string, resHeaders: Record<string, string>, redirectOptions: Client.request.Options, next: () => void) => void;
/**
* TLS list of TLS ciphers to override node's default.
*/
readonly ciphers?: string;
/**
* An object containing the request headers.
*/
readonly headers?: Record<string, string>;
/**
* Determines how to handle gzipped payloads.
*
* @default false
*/
readonly gunzip?: boolean | 'force';
/**
* The request body as a string, Buffer, readable stream, or an object that can be serialized using `JSON.stringify()`.
*/
readonly payload?: Payload;
/**
* Enables redirects on 303 responses (using GET).
*
* @default false
*/
readonly redirect303?: boolean;
/**
* Overrides the HTTP method used when following 301 and 302 redirections. Defaults to the original method.
*/
readonly redirectMethod?: string;
/**
* The maximum number of redirects to follow.
*
* @default false
*/
readonly redirects?: number | false;
/**
* A function to call when a redirect was triggered.
*
* @param statusCode - HTTP status code of the response that triggered the redirect.
* @param location - the redirected location string.
* @param req - the new ClientRequest object which replaces the one initially returned.
*/
readonly redirected?: (statusCode: number, location: string, req: Http.ClientRequest) => void;
/**
* TLS flag indicating whether the client should reject a response from a server with invalid certificates.
*/
readonly rejectUnauthorized?: boolean;
/**
* TLS flag indicating the SSL method to use, e.g. `SSLv3_method` to force SSL version 3.
*/
readonly secureProtocol?: string;
/**
* A UNIX socket path string for direct server connection.
*/
readonly socketPath?: string;
/**
* Number of milliseconds to wait without receiving a response before aborting the request.
*
* @default 0
*/
readonly timeout?: number;
}
type Payload = string | Buffer | Stream.Readable | object;
interface Response<T = Buffer> {
res: Http.IncomingMessage;
payload: T;
}
}
namespace read {
interface Options {
/**
* Determines how to handle gzipped payloads.
*
* @default false
*/
readonly gunzip?: boolean | 'force';
/**
* Determines how to parse the payload as JSON.
*/
readonly json?: boolean | 'strict' | 'force';
/**
* The maximum allowed response payload size.
*
* @default 0
*/
readonly maxBytes?: number;
/**
* The number of milliseconds to wait while reading data before aborting handling of the response.
*
* @default 0
*/
readonly timeout?: number;
}
}
namespace toReadableStream {
type Item = string | Buffer;
type Payload = Item | Item[];
}
namespace parseCacheControl {
interface Parameters {
'max-age'?: number;
[key: string]: string | number | undefined;
}
}
}
declare const client: Client;
export = client;

688
node_modules/@hapi/wreck/lib/index.js generated vendored Executable file
View File

@@ -0,0 +1,688 @@
'use strict';
const Events = require('events');
const Http = require('http');
const Https = require('https');
const Stream = require('stream');
const Url = require('url');
const Zlib = require('zlib');
const Boom = require('@hapi/boom');
const Bourne = require('@hapi/bourne');
const Hoek = require('@hapi/hoek');
const Payload = require('./payload');
const Recorder = require('./recorder');
const Tap = require('./tap');
const internals = {
jsonRegex: /^application\/([a-z0-9.]*[+-]json|json)$/,
shallowOptions: ['agent', 'agents', 'beforeRedirect', 'payload', 'redirected'],
httpOptions: ['secureProtocol', 'ciphers', 'lookup', 'family', 'hints']
};
// New instance is exported as module.exports
internals.Client = class {
constructor(options = {}) {
Hoek.assert(!options.agents || options.agents.https && options.agents.http && options.agents.httpsAllowUnauthorized, 'Option agents must include "http", "https", and "httpsAllowUnauthorized"');
this._defaults = Hoek.clone(options, { shallow: internals.shallowOptions });
this.agents = this._defaults.agents || {
https: new Https.Agent({ maxSockets: Infinity }),
http: new Http.Agent({ maxSockets: Infinity }),
httpsAllowUnauthorized: new Https.Agent({ maxSockets: Infinity, rejectUnauthorized: false })
};
if (this._defaults.events) {
this.events = new Events.EventEmitter();
}
}
defaults(options) {
Hoek.assert(options && typeof options === 'object', 'options must be provided to defaults');
options = Hoek.applyToDefaults(this._defaults, options, { shallow: internals.shallowOptions });
return new internals.Client(options);
}
request(method, url, options = {}) {
try {
options = Hoek.applyToDefaults(this._defaults, options, { shallow: internals.shallowOptions });
Hoek.assert(options.payload === undefined || typeof options.payload === 'string' || typeof options.payload === 'object', 'options.payload must be a string, a Buffer, a Stream, or an Object');
Hoek.assert(internals.isNullOrUndefined(options.agent) || typeof options.rejectUnauthorized !== 'boolean', 'options.agent cannot be set to an Agent at the same time as options.rejectUnauthorized is set');
Hoek.assert(internals.isNullOrUndefined(options.beforeRedirect) || typeof options.beforeRedirect === 'function', 'options.beforeRedirect must be a function');
Hoek.assert(internals.isNullOrUndefined(options.redirected) || typeof options.redirected === 'function', 'options.redirected must be a function');
Hoek.assert(options.gunzip === undefined || typeof options.gunzip === 'boolean' || options.gunzip === 'force', 'options.gunzip must be a boolean or "force"');
}
catch (err) {
return Promise.reject(err);
}
if (options.baseUrl) {
url = internals.resolveUrl(options.baseUrl, url);
delete options.baseUrl;
}
const relay = {};
const req = this._request(method, url, options, relay);
const promise = new Promise((resolve, reject) => {
relay.callback = (err, res) => {
if (err) {
reject(err);
return;
}
resolve(res);
return;
};
});
promise.req = req;
return promise;
}
_request(method, url, options, relay, _trace) {
const uri = {};
if (options.socketPath) {
uri.socketPath = options.socketPath;
const parsedUri = new Url.URL(url, `unix://${options.socketPath}`);
internals.applyUrlToOptions(uri, {
host: '', // host must be empty according to https://tools.ietf.org/html/rfc2616#section-14.23
protocol: 'http:',
hash: parsedUri.hash,
search: parsedUri.search,
searchParams: parsedUri.searchParams,
pathname: parsedUri.pathname,
href: parsedUri.href
});
}
else {
uri.setHost = false;
const parsedUri = new Url.URL(url);
internals.applyUrlToOptions(uri, parsedUri);
}
uri.method = method.toUpperCase();
uri.headers = Object.create(null);
const usedHeaders = new Set();
if (options.headers) {
for (const [key, value] of Object.entries(options.headers)) {
if (value !== undefined) {
uri.headers[key] = value;
usedHeaders.add(key.toLowerCase());
}
}
}
if (!usedHeaders.has('host')) {
uri.headers.host = uri.host;
}
if (options.payload && typeof options.payload === 'object' && !(options.payload instanceof Stream) && !Buffer.isBuffer(options.payload)) {
options.payload = JSON.stringify(options.payload);
if (!usedHeaders.has('content-type')) {
uri.headers['content-type'] = 'application/json';
}
}
if (options.gunzip &&
!usedHeaders.has('accept-encoding')) {
uri.headers['accept-encoding'] = 'gzip';
}
const payloadSupported = uri.method !== 'GET' && uri.method !== 'HEAD' && !internals.isNullOrUndefined(options.payload);
if (payloadSupported &&
(typeof options.payload === 'string' || Buffer.isBuffer(options.payload)) &&
!usedHeaders.has('content-length')) {
uri.headers['content-length'] = Buffer.isBuffer(options.payload) ? options.payload.length : Buffer.byteLength(options.payload);
}
let redirects = options.hasOwnProperty('redirects') ? options.redirects : false; // Needed to allow 0 as valid value when passed recursively
_trace = _trace ?? [];
_trace.push({ method: uri.method, url });
const client = uri.protocol === 'https:' ? Https : Http;
for (const option of internals.httpOptions) {
if (options[option] !== undefined) {
uri[option] = options[option];
}
}
if (options.rejectUnauthorized !== undefined &&
uri.protocol === 'https:') {
uri.agent = options.rejectUnauthorized ? this.agents.https : this.agents.httpsAllowUnauthorized;
}
else if (options.agent ||
options.agent === false) {
uri.agent = options.agent;
}
else {
uri.agent = uri.protocol === 'https:' ? this.agents.https : this.agents.http;
}
this._emit('preRequest', uri, options);
const start = Date.now();
const req = client.request(uri);
this._emit('request', req);
let shadow = null; // A copy of the streamed request payload when redirects are enabled
let timeoutId;
const onError = (err) => {
err.trace = _trace;
return finishOnce(Boom.badGateway('Client request error', err));
};
const onAbort = () => {
if (!req.socket) {
// Fake an ECONNRESET error on early abort
const error = new Error('socket hang up');
error.code = 'ECONNRESET';
finishOnce(error);
}
};
req.once('error', onError);
const onResponse = (res) => {
// Pass-through response
const statusCode = res.statusCode;
const redirectMethod = internals.redirectMethod(statusCode, uri.method, options);
if (redirects === false ||
!redirectMethod) {
return finishOnce(null, res);
}
// Redirection
res.destroy();
if (redirects === 0) {
return finishOnce(Boom.badGateway('Maximum redirections reached', _trace));
}
let location = res.headers.location;
if (!location) {
return finishOnce(Boom.badGateway('Received redirection without location', _trace));
}
if (!/^https?:/i.test(location)) {
location = Url.resolve(uri.href, location);
}
const redirectOptions = Hoek.clone(options, { shallow: internals.shallowOptions });
redirectOptions.payload = shadow ?? options.payload; // shadow must be ready at this point if set
redirectOptions.redirects = --redirects;
if (timeoutId) {
clearTimeout(timeoutId);
const elapsed = Date.now() - start;
redirectOptions.timeout = (redirectOptions.timeout - elapsed).toString(); // stringify to not drop timeout when === 0
}
// When redirecting to a new hostname, remove the authorization and cookie headers
if (redirectOptions.headers) {
const parsedLocation = new URL(location);
if (uri.hostname !== parsedLocation.hostname) {
for (const header of Object.keys(redirectOptions.headers)) {
const lowerHeader = header.toLowerCase();
if (lowerHeader === 'authorization' || lowerHeader === 'cookie') {
delete redirectOptions.headers[header];
}
}
}
}
const followRedirect = (err) => {
if (err) {
err.trace = _trace;
return finishOnce(Boom.badGateway('Invalid redirect', err));
}
const redirectReq = this._request(redirectMethod, location, redirectOptions, { callback: finishOnce }, _trace);
if (options.redirected) {
options.redirected(statusCode, location, redirectReq);
}
};
if (!options.beforeRedirect) {
return followRedirect();
}
return options.beforeRedirect(redirectMethod, statusCode, location, res.headers, redirectOptions, followRedirect);
};
// Register handlers
const finish = (err, res) => {
if (err) {
req.abort();
}
req.removeListener('response', onResponse);
req.removeListener('error', onError);
req.removeListener('abort', onAbort);
req.on('error', Hoek.ignore);
clearTimeout(timeoutId);
this._emit('response', err, { req, res, start, uri });
return relay.callback(err, res);
};
const finishOnce = Hoek.once(finish);
req.once('response', onResponse);
if (options.timeout) {
timeoutId = setTimeout(() => finishOnce(Boom.gatewayTimeout('Client request timeout')), options.timeout);
}
req.on('abort', onAbort);
// Write payload
if (payloadSupported) {
if (options.payload instanceof Stream) {
let stream = options.payload;
if (redirects) {
const collector = new Tap();
collector.once('finish', () => {
shadow = collector.collect();
});
stream = options.payload.pipe(collector);
}
internals.deferPipeUntilSocketConnects(req, stream);
return req;
}
req.write(options.payload);
}
// Finalize request
req.end();
return req;
}
_emit(...args) {
if (this.events) {
this.events.emit(...args);
}
}
read(res, options = {}) {
return new Promise((resolve, reject) => {
this._read(res, options, (err, payload) => {
if (err) {
reject(err);
return;
}
resolve(payload);
return;
});
});
}
_read(res, options, callback) {
options = Hoek.applyToDefaults(this._defaults, options, { shallow: internals.shallowOptions });
// Finish once
let clientTimeoutId = null;
const finish = (err, buffer) => {
clearTimeout(clientTimeoutId);
reader.removeListener('error', onReaderError);
reader.removeListener('finish', onReaderFinish);
res.removeListener('error', onResError);
res.removeListener('close', onResAborted);
res.removeListener('aborted', onResAborted);
res.on('error', Hoek.ignore);
if (err) {
return callback(err);
}
if (!options.json) {
return callback(null, buffer);
}
// Parse JSON
if (options.json === 'force') {
return internals.tryParseBuffer(buffer, callback);
}
// 'strict' or true
const contentType = res.headers?.['content-type'] ?? '';
const mime = contentType.split(';')[0].trim().toLowerCase();
if (!internals.jsonRegex.test(mime)) {
if (options.json === 'strict') {
return callback(Boom.notAcceptable('The content-type is not JSON compatible'));
}
return callback(null, buffer);
}
return internals.tryParseBuffer(buffer, callback);
};
const finishOnce = Hoek.once(finish);
const clientTimeout = options.timeout;
if (clientTimeout &&
clientTimeout > 0) {
clientTimeoutId = setTimeout(() => finishOnce(Boom.clientTimeout()), clientTimeout);
}
// Hander errors
const onResError = (err) => {
return finishOnce(err.isBoom ? err : Boom.internal('Payload stream error', err));
};
const onResAborted = () => {
if (!res.complete) {
finishOnce(Boom.internal('Payload stream closed prematurely'));
}
};
res.once('error', onResError);
res.once('close', onResAborted);
res.once('aborted', onResAborted);
// Read payload
const reader = new Recorder({ maxBytes: options.maxBytes });
const onReaderError = (err) => {
if (res.destroy) { // GZip stream has no destroy() method
res.destroy();
}
return finishOnce(err);
};
reader.once('error', onReaderError);
const onReaderFinish = () => {
return finishOnce(null, reader.collect());
};
reader.once('finish', onReaderFinish);
if (options.gunzip) {
const contentEncoding = options.gunzip === 'force' ?
'gzip' :
res.headers?.['content-encoding'] ?? '';
if (/^(x-)?gzip(\s*,\s*identity)?$/.test(contentEncoding)) {
const gunzip = Zlib.createGunzip();
gunzip.once('error', onReaderError);
res.pipe(gunzip).pipe(reader);
return;
}
}
res.pipe(reader);
}
toReadableStream(payload, encoding) {
return new Payload(payload, encoding);
}
parseCacheControl(field) {
/*
Cache-Control = 1#cache-directive
cache-directive = token [ "=" ( token / quoted-string ) ]
token = [^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+
quoted-string = "(?:[^"\\]|\\.)*"
*/
// 1: directive = 2: token 3: quoted-string
const regex = /(?:^|(?:\s*\,\s*))([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g;
const header = {};
const error = field.replace(regex, ($0, $1, $2, $3) => {
const value = $2 || $3;
header[$1] = value ? value.toLowerCase() : true;
return '';
});
if (header['max-age']) {
try {
const maxAge = parseInt(header['max-age'], 10);
if (isNaN(maxAge)) {
return null;
}
header['max-age'] = maxAge;
}
catch (err) { }
}
return error ? null : header;
}
// Shortcuts
get(uri, options) {
return this._shortcut('GET', uri, options);
}
post(uri, options) {
return this._shortcut('POST', uri, options);
}
patch(uri, options) {
return this._shortcut('PATCH', uri, options);
}
put(uri, options) {
return this._shortcut('PUT', uri, options);
}
delete(uri, options) {
return this._shortcut('DELETE', uri, options);
}
async _shortcut(method, uri, options = {}) {
const res = await this.request(method, uri, options);
let payload;
try {
payload = await this.read(res, options);
}
catch (err) {
err.data = err.data ?? {};
err.data.res = res;
throw err;
}
if (res.statusCode < 400) {
return { res, payload };
}
// Response error
const data = {
isResponseError: true,
headers: res.headers,
res,
payload
};
throw new Boom.Boom(`Response Error: ${res.statusCode} ${res.statusMessage}`, { statusCode: res.statusCode, data });
}
};
// baseUrl needs to end in a trailing / if it contains paths that need to be preserved
internals.resolveUrl = function (baseUrl, path) {
if (!path) {
return baseUrl;
}
// Will default to path if it's not a relative URL
const url = new Url.URL(path, baseUrl);
return Url.format(url);
};
internals.deferPipeUntilSocketConnects = function (req, stream) {
const onSocket = (socket) => {
if (!socket.connecting) {
return onSocketConnect();
}
socket.once('connect', onSocketConnect);
};
const onSocketConnect = () => {
stream.pipe(req);
stream.removeListener('error', onStreamError);
};
const onStreamError = (err) => {
req.emit('error', err);
};
req.once('socket', onSocket);
stream.on('error', onStreamError);
};
internals.redirectMethod = function (code, method, options) {
switch (code) {
case 301:
case 302:
return options.redirectMethod || method;
case 303:
if (options.redirect303) {
return 'GET';
}
break;
case 307:
case 308:
return method;
}
return null;
};
internals.tryParseBuffer = function (buffer, next) {
if (buffer.length === 0) {
return next(null, null);
}
let payload;
try {
payload = Bourne.parse(buffer.toString());
}
catch (err) {
return next(Boom.badGateway(err.message, { payload: buffer }));
}
return next(null, payload);
};
internals.applyUrlToOptions = (options, url) => {
options.host = url.host;
options.origin = url.origin;
options.searchParams = url.searchParams;
options.protocol = url.protocol;
options.hostname = typeof url.hostname === 'string' && url.hostname.startsWith('[') ? url.hostname.slice(1, -1) : url.hostname;
options.hash = url.hash;
options.search = url.search;
options.pathname = url.pathname;
options.path = `${url.pathname}${url.search}`;
options.href = url.href;
if (url.port !== '') {
options.port = Number(url.port);
}
if (url.username || url.password) {
options.auth = `${url.username}:${url.password}`;
options.username = url.username;
options.password = url.password;
}
return options;
};
internals.isNullOrUndefined = (val) => [null, undefined].includes(val);
module.exports = new internals.Client();

38
node_modules/@hapi/wreck/lib/payload.js generated vendored Executable file
View File

@@ -0,0 +1,38 @@
'use strict';
const Stream = require('stream');
const internals = {};
module.exports = internals.Payload = class extends Stream.Readable {
constructor(payload, encoding) {
super();
const data = [].concat(payload || '');
let size = 0;
for (let i = 0; i < data.length; ++i) {
const chunk = data[i];
size = size + chunk.length;
data[i] = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
}
this._data = Buffer.concat(data, size);
this._position = 0;
this._encoding = encoding || 'utf8';
}
_read(size) {
const chunk = this._data.slice(this._position, this._position + size);
this.push(chunk, this._encoding);
this._position = this._position + chunk.length;
if (this._position >= this._data.length) {
this.push(null);
}
}
};

40
node_modules/@hapi/wreck/lib/recorder.js generated vendored Executable file
View File

@@ -0,0 +1,40 @@
'use strict';
const Stream = require('stream');
const Boom = require('@hapi/boom');
const internals = {};
module.exports = internals.Recorder = class extends Stream.Writable {
constructor(options) {
super();
this.settings = options; // No need to clone since called internally with new object
this.buffers = [];
this.length = 0;
}
_write(chunk, encoding, next) {
if (this.settings.maxBytes &&
this.length + chunk.length > this.settings.maxBytes) {
return this.emit('error', Boom.entityTooLarge('Payload content length greater than maximum allowed: ' + this.settings.maxBytes));
}
this.length = this.length + chunk.length;
this.buffers.push(chunk);
next();
}
collect() {
const buffer = (this.buffers.length === 0 ? Buffer.alloc(0) : (this.buffers.length === 1 ? this.buffers[0] : Buffer.concat(this.buffers, this.length)));
return buffer;
}
};

29
node_modules/@hapi/wreck/lib/tap.js generated vendored Executable file
View File

@@ -0,0 +1,29 @@
'use strict';
const Stream = require('stream');
const Payload = require('./payload');
const internals = {};
module.exports = internals.Tap = class extends Stream.Transform {
constructor() {
super();
this.buffers = [];
}
_transform(chunk, encoding, next) {
this.buffers.push(chunk);
next(null, chunk);
}
collect() {
return new Payload(this.buffers);
}
};

32
node_modules/@hapi/wreck/package.json generated vendored Executable file
View File

@@ -0,0 +1,32 @@
{
"name": "@hapi/wreck",
"description": "HTTP Client Utilities",
"version": "18.1.0",
"repository": "git://github.com/hapijs/wreck",
"main": "lib/index",
"types": "lib/index.d.ts",
"keywords": [
"utilities",
"http",
"client"
],
"files": [
"lib"
],
"dependencies": {
"@hapi/boom": "^10.0.1",
"@hapi/bourne": "^3.0.0",
"@hapi/hoek": "^11.0.2"
},
"devDependencies": {
"@hapi/code": "^9.0.3",
"@hapi/lab": "^25.1.2",
"@types/node": "^17.0.31",
"typescript": "~4.6.4"
},
"scripts": {
"test": "lab -t 100 -L -a @hapi/code -m 10000 -Y",
"test-cov-html": "lab -r html -o coverage.html -a @hapi/code -m 10000"
},
"license": "BSD-3-Clause"
}