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

12
node_modules/@hapi/accept/LICENSE.md generated vendored Executable file
View File

@@ -0,0 +1,12 @@
Copyright (c) 2014-2022, Project contributors
Copyright (c) 2014-2020, Sideway Inc
Copyright (c) 2015-2016, Mark Bradshaw
Copyright (c) 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/accept/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/accept
#### HTTP Accept-* headers parsing.
**accept** 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/accept/)
- [Version status](https://hapi.dev/resources/status/#accept) (builds, dependencies, node versions, licenses, eol)
- [Changelog](https://hapi.dev/family/accept/changelog/)
- [Project policies](https://hapi.dev/policies/)
- [Free and commercial support options](https://hapi.dev/support/)

232
node_modules/@hapi/accept/lib/header.js generated vendored Executable file
View File

@@ -0,0 +1,232 @@
'use strict';
const Hoek = require('@hapi/hoek');
const Boom = require('@hapi/boom');
const internals = {};
exports.selection = function (header, preferences, options) {
const selections = exports.selections(header, preferences, options);
return selections.length ? selections[0] : '';
};
exports.selections = function (header, preferences, options) {
Hoek.assert(!preferences || Array.isArray(preferences), 'Preferences must be an array');
return internals.parse(header || '', preferences, options);
};
// RFC 7231 Section 5.3.3 (https://tools.ietf.org/html/rfc7231#section-5.3.3)
//
// Accept-Charset = *( "," OWS ) ( ( charset / "*" ) [ weight ] ) *( OWS "," [ OWS ( ( charset / "*" ) [ weight ] ) ] )
// charset = token
//
// Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
// RFC 7231 Section 5.3.4 (https://tools.ietf.org/html/rfc7231#section-5.3.4)
//
// Accept-Encoding = [ ( "," / ( codings [ weight ] ) ) *( OWS "," [ OWS ( codings [ weight ] ) ] ) ]
// codings = content-coding / "identity" / "*"
// content-coding = token
//
// Accept-Encoding: compress, gzip
// Accept-Encoding:
// Accept-Encoding: *
// Accept-Encoding: compress;q=0.5, gzip;q=1.0
// Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
// RFC 7231 Section 5.3.5 (https://tools.ietf.org/html/rfc7231#section-5.3.5)
//
// Accept-Language = *( "," OWS ) ( language-range [ weight ] ) *( OWS "," [ OWS ( language-range [ weight ] ) ] )
// language-range = ( 1*8ALPHA *( "-" 1*8alphanum ) ) / "*" ; [RFC4647], Section 2.1
// alphanum = ALPHA / DIGIT
//
// Accept-Language: da, en-gb;q=0.8, en;q=0.7
// token = 1*tchar
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
// / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
// / DIGIT / ALPHA
// ; any VCHAR, except delimiters
// OWS = *( SP / HTAB )
// RFC 7231 Section 5.3.1 (https://tools.ietf.org/html/rfc7231#section-5.3.1)
//
// The weight is normalized to a real number in the range 0 through 1,
// where 0.001 is the least preferred and 1 is the most preferred; a
// value of 0 means "not acceptable". If no "q" parameter is present,
// the default weight is 1.
//
// weight = OWS ";" OWS "q=" qvalue
// qvalue = ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] )
internals.parse = function (raw, preferences, options) {
// Normalize header (remove spaces and tabs)
const header = raw.replace(/[ \t]/g, '');
// Normalize preferences
const lowers = new Map();
if (preferences) {
let pos = 0;
for (const preference of preferences) {
const lower = preference.toLowerCase();
lowers.set(lower, { orig: preference, pos: pos++ });
if (options.prefixMatch) {
const parts = lower.split('-');
while (parts.pop(), parts.length > 0) {
const joined = parts.join('-');
if (!lowers.has(joined)) {
lowers.set(joined, { orig: preference, pos: pos++ });
}
}
}
}
}
// Parse selections
const parts = header.split(',');
const selections = [];
const map = new Set();
for (let i = 0; i < parts.length; ++i) {
const part = parts[i];
if (!part) { // Ignore empty parts or leading commas
continue;
}
// Parse parameters
const params = part.split(';');
if (params.length > 2) {
throw Boom.badRequest(`Invalid ${options.type} header`);
}
let token = params[0].toLowerCase();
if (!token) {
throw Boom.badRequest(`Invalid ${options.type} header`);
}
if (options.equivalents?.has(token)) {
token = options.equivalents.get(token);
}
const selection = {
token,
pos: i,
q: 1
};
if (preferences &&
lowers.has(token)) {
selection.pref = lowers.get(token).pos;
}
map.add(selection.token);
// Parse q=value
if (params.length === 2) {
const q = params[1];
const [key, value] = q.split('=');
if (!value ||
key !== 'q' && key !== 'Q') {
throw Boom.badRequest(`Invalid ${options.type} header`);
}
const score = parseFloat(value);
if (score === 0) {
continue;
}
if (Number.isFinite(score) &&
score <= 1 &&
score >= 0.001) {
selection.q = score;
}
}
selections.push(selection); // Only add allowed selections (q !== 0)
}
// Sort selection based on q and then position in header
selections.sort(internals.sort);
// Extract tokens
const values = selections.map((selection) => selection.token);
if (options.default &&
!map.has(options.default)) {
values.push(options.default);
}
if (!preferences?.length) {
return values;
}
const preferred = [];
for (const selection of values) {
if (selection === '*') {
for (const [preference, value] of lowers) {
if (!map.has(preference)) {
preferred.push(value.orig);
}
}
}
else {
const lower = selection.toLowerCase();
if (lowers.has(lower)) {
preferred.push(lowers.get(lower).orig);
}
}
}
return preferred;
};
internals.sort = function (a, b) {
const aFirst = -1;
const bFirst = 1;
if (b.q !== a.q) {
return b.q - a.q;
}
if (b.pref !== a.pref) {
if (a.pref === undefined) {
return bFirst;
}
if (b.pref === undefined) {
return aFirst;
}
return a.pref - b.pref;
}
return a.pos - b.pos;
};

114
node_modules/@hapi/accept/lib/index.d.ts generated vendored Executable file
View File

@@ -0,0 +1,114 @@
/**
* Identifies the best character-set for an HTTP response based on the HTTP request Accept-Charset header.
*
* @param header - the HTTP Accept-Charset header content.
* @param preferences - an optional array of character-set strings in order of server preference.
*
* @return a string with the preferred accepted character-set.
*/
export function charset(header?: string, preferences?: readonly string[]): string;
/**
* Sorts the character-sets in the HTTP request Accept-Charset header based on client preference from most to least desired.
*
* @param header - the HTTP Accept-Charset header content.
*
* @return an array of strings of character-sets sorted from the most to the least desired.
*/
export function charsets(header?: string): string[];
/**
* Identifies the best encoding for an HTTP response based on the HTTP request Accept-Encoding header.
*
* @param header - the HTTP Accept-Encoding header content.
* @param preferences - an optional array of encoding strings in order of server preference.
*
* @return a string with the preferred accepted encoding.
*/
export function encoding(header?: string, preferences?: readonly string[]): string;
/**
* Sorts the encodings in the HTTP request Accept-Encoding header based on client preference from most to least desired.
*
* @param header - the HTTP Accept-Encoding header content.
*
* @return an array of strings of encodings sorted from the most to the least desired.
*/
export function encodings(header?: string): string[];
/**
* Identifies the best language for an HTTP response based on the HTTP request Accept-Language header.
*
* @param header - the HTTP Accept-Language header content.
* @param preferences - an optional array of language strings in order of server preference.
*
* @return a string with the preferred accepted language.
*/
export function language(header?: string, preferences?: readonly string[]): string;
/**
* Sorts the languages in the HTTP request Accept-Language header based on client preference from most to least desired.
*
* @param header - the HTTP Accept-Language header content.
*
* @return an array of strings of languages sorted from the most to the least desired.
*/
export function languages(header?: string): string[];
/**
* Identifies the best media-type for an HTTP response based on the HTTP request Accept header.
*
* @param header - the HTTP Accept header content.
* @param preferences - an optional array of media-type strings in order of server preference.
*
* @return a string with the preferred accepted media-type.
*/
export function mediaType(header?: string, preferences?: readonly string[]): string;
/**
* Sorts the media-types in the HTTP request Accept header based on client preference from most to least desired.
*
* @param header - the HTTP Accept header content.
* @param preferences - an optional array of media-type strings in order of server preference.
*
* @return an array of strings of media-types sorted from the most to the least desired.
*/
export function mediaTypes(header?: string, preferences?: readonly string[]): string[];
/**
* Parses the Accept-* headers of an HTTP request and returns an array of client preferences for each header.
*
* @param headers - the HTTP request headers object.
*
* @return an object with a key for each accept header result.
*/
export function parseAll(headers: parseAll.Headers): parseAll.Result;
export namespace parseAll {
interface Headers {
readonly 'accept-charset'?: string;
readonly 'accept-encoding'?: string;
readonly 'accept-language'?: string;
readonly accept?: string;
readonly [header: string]: any;
}
interface Result {
charsets: string[];
encodings: string[];
languages: string[];
mediaTypes: string[];
}
}

48
node_modules/@hapi/accept/lib/index.js generated vendored Executable file
View File

@@ -0,0 +1,48 @@
'use strict';
const Header = require('./header');
const Media = require('./media');
const internals = {
options: {
charset: {
type: 'accept-charset'
},
encoding: {
type: 'accept-encoding',
default: 'identity',
equivalents: new Map([
['x-compress', 'compress'],
['x-gzip', 'gzip']
])
},
language: {
type: 'accept-language',
prefixMatch: true
}
}
};
for (const type in internals.options) {
exports[type] = (header, preferences) => Header.selection(header, preferences, internals.options[type]);
exports[`${type}s`] = (header, preferences) => Header.selections(header, preferences, internals.options[type]);
}
exports.mediaType = (header, preferences) => Media.selection(header, preferences);
exports.mediaTypes = (header, preferences) => Media.selections(header, preferences);
exports.parseAll = function (requestHeaders) {
return {
charsets: exports.charsets(requestHeaders['accept-charset']),
encodings: exports.encodings(requestHeaders['accept-encoding']),
languages: exports.languages(requestHeaders['accept-language']),
mediaTypes: exports.mediaTypes(requestHeaders.accept)
};
};

322
node_modules/@hapi/accept/lib/media.js generated vendored Executable file
View File

@@ -0,0 +1,322 @@
'use strict';
const Hoek = require('@hapi/hoek');
const Boom = require('@hapi/boom');
const internals = {};
exports.selection = function (header, preferences) {
const selections = exports.selections(header, preferences);
return selections.length ? selections[0] : '';
};
exports.selections = function (header, preferences) {
Hoek.assert(!preferences || Array.isArray(preferences), 'Preferences must be an array');
return internals.parse(header, preferences);
};
// RFC 7231 Section 5.3.2 (https://tools.ietf.org/html/rfc7231#section-5.3.2)
//
// Accept = [ ( "," / ( media-range [ accept-params ] ) ) *( OWS "," [ OWS ( media-range [ accept-params ] ) ] ) ]
// media-range = ( "*/*" / ( type "/*" ) / ( type "/" subtype ) ) *( OWS ";" OWS parameter )
// accept-params = weight *accept-ext
// accept-ext = OWS ";" OWS token [ "=" ( token / quoted-string ) ]
// type = token
// subtype = token
// parameter = token "=" ( token / quoted-string )
//
// quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
// qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
// obs-text = %x80-FF
// quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
// VCHAR = %x21-7E ; visible (printing) characters
// token = 1*tchar
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
// OWS = *( SP / HTAB )
//
// Accept: audio/*; q=0.2, audio/basic
// Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c
// Accept: text/plain, application/json;q=0.5, text/html, */*; q = 0.1
// Accept: text/plain, application/json;q=0.5, text/html, text/drop;q=0
// Accept: text/*, text/plain, text/plain;format=flowed, */*
// Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5
// RFC 7231 Section 5.3.1 (https://tools.ietf.org/html/rfc7231#section-5.3.1)
//
// The weight is normalized to a real number in the range 0 through 1,
// where 0.001 is the least preferred and 1 is the most preferred; a
// value of 0 means "not acceptable". If no "q" parameter is present,
// the default weight is 1.
//
// weight = OWS ";" OWS "q=" qvalue
// qvalue = ( "0" [ "." 0*3DIGIT ] ) / ( "1" [ "." 0*3("0") ] )
// */* type/* type/subtype
internals.validMediaRx = /^(?:\*\/\*)|(?:[\w\!#\$%&'\*\+\-\.\^`\|~]+\/\*)|(?:[\w\!#\$%&'\*\+\-\.\^`\|~]+\/[\w\!#\$%&'\*\+\-\.\^`\|~]+)$/;
internals.parse = function (raw, preferences) {
// Normalize header (remove spaces and temporary remove quoted strings)
const { header, quoted } = internals.normalize(raw);
// Parse selections
const parts = header.split(',');
const selections = [];
const map = {};
for (let i = 0; i < parts.length; ++i) {
const part = parts[i];
if (!part) { // Ignore empty parts or leading commas
continue;
}
// Parse parameters
const pairs = part.split(';');
const token = pairs.shift().toLowerCase();
if (!internals.validMediaRx.test(token)) { // Ignore invalid types
continue;
}
const selection = {
token,
params: {},
exts: {},
pos: i
};
// Parse key=value
let target = 'params';
for (const pair of pairs) {
const kv = pair.split('=');
if (kv.length !== 2 ||
!kv[1]) {
throw Boom.badRequest(`Invalid accept header`);
}
const key = kv[0];
let value = kv[1];
if (key === 'q' ||
key === 'Q') {
target = 'exts';
value = parseFloat(value);
if (!Number.isFinite(value) ||
value > 1 ||
(value < 0.001 && value !== 0)) {
value = 1;
}
selection.q = value;
}
else {
if (value[0] === '"') {
value = `"${quoted[value]}"`;
}
selection[target][kv[0]] = value;
}
}
const params = Object.keys(selection.params);
selection.original = [''].concat(params.map((key) => `${key}=${selection.params[key]}`)).join(';');
selection.specificity = params.length;
if (selection.q === undefined) { // Default no preference to q=1 (top preference)
selection.q = 1;
}
const tparts = selection.token.split('/');
selection.type = tparts[0];
selection.subtype = tparts[1];
map[selection.token] = selection;
if (selection.q) { // Skip denied selections (q=0)
selections.push(selection);
}
}
// Sort selection based on q and then position in header
selections.sort(internals.sort);
return internals.preferences(map, selections, preferences);
};
internals.normalize = function (raw) {
raw = raw || '*/*';
const normalized = {
header: raw,
quoted: {}
};
if (raw.includes('"')) {
let i = 0;
normalized.header = raw.replace(/="([^"]*)"/g, ($0, $1) => {
const key = '"' + ++i;
normalized.quoted[key] = $1;
return '=' + key;
});
}
normalized.header = normalized.header.replace(/[ \t]/g, '');
return normalized;
};
internals.sort = function (a, b) {
// Sort by quality score
if (b.q !== a.q) {
return b.q - a.q;
}
// Sort by type
if (a.type !== b.type) {
return internals.innerSort(a, b, 'type');
}
// Sort by subtype
if (a.subtype !== b.subtype) {
return internals.innerSort(a, b, 'subtype');
}
// Sort by specificity
if (a.specificity !== b.specificity) {
return b.specificity - a.specificity;
}
return a.pos - b.pos;
};
internals.innerSort = function (a, b, key) {
const aFirst = -1;
const bFirst = 1;
if (a[key] === '*') {
return bFirst;
}
if (b[key] === '*') {
return aFirst;
}
return a[key] < b[key] ? aFirst : bFirst; // Group alphabetically
};
internals.preferences = function (map, selections, preferences) {
// Return selections if no preferences
if (!preferences?.length) {
return selections.map((selection) => selection.token + selection.original);
}
// Map wildcards and filter selections to preferences
const lowers = Object.create(null);
const flat = Object.create(null);
let any = false;
for (const preference of preferences) {
const lower = preference.toLowerCase();
flat[lower] = preference;
const parts = lower.split('/');
const type = parts[0];
const subtype = parts[1];
if (type === '*') {
Hoek.assert(subtype === '*', 'Invalid media type preference contains wildcard type with a subtype');
any = true;
continue;
}
lowers[type] = lowers[type] ?? Object.create(null);
lowers[type][subtype] = preference;
}
const preferred = [];
for (const selection of selections) {
const token = selection.token;
const { type, subtype } = map[token];
const subtypes = lowers[type];
// */*
if (type === '*') {
for (const preference of Object.keys(flat)) {
if (!map[preference]) {
preferred.push(flat[preference]);
}
}
if (any) {
preferred.push('*/*');
}
continue;
}
// any
if (any) {
preferred.push((flat[token] || token) + selection.original);
continue;
}
// type/subtype
if (subtype !== '*') {
const pref = flat[token];
if (pref ||
(subtypes && subtypes['*'])) {
preferred.push((pref || token) + selection.original);
}
continue;
}
// type/*
if (subtypes) {
for (const psub of Object.keys(subtypes)) {
if (!map[`${type}/${psub}`]) {
preferred.push(subtypes[psub]);
}
}
}
}
return preferred;
};

38
node_modules/@hapi/accept/package.json generated vendored Executable file
View File

@@ -0,0 +1,38 @@
{
"name": "@hapi/accept",
"description": "HTTP Accept-* headers parsing",
"version": "6.0.3",
"repository": "git://github.com/hapijs/accept",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib"
],
"keywords": [
"HTTP",
"header",
"accept",
"accept-encoding"
],
"eslintConfig": {
"extends": [
"plugin:@hapi/module"
]
},
"dependencies": {
"@hapi/boom": "^10.0.1",
"@hapi/hoek": "^11.0.2"
},
"devDependencies": {
"@hapi/code": "^9.0.3",
"@hapi/eslint-plugin": "*",
"@hapi/lab": "^25.1.2",
"@types/node": "^17.0.31",
"typescript": "~4.6.4"
},
"scripts": {
"test": "lab -a @hapi/code -t 100 -L -Y",
"test-cov-html": "lab -a @hapi/code -r html -o coverage.html"
},
"license": "BSD-3-Clause"
}