tsoa
This commit is contained in:
12
node_modules/@hapi/accept/LICENSE.md
generated
vendored
Executable file
12
node_modules/@hapi/accept/LICENSE.md
generated
vendored
Executable 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
17
node_modules/@hapi/accept/README.md
generated
vendored
Executable 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
232
node_modules/@hapi/accept/lib/header.js
generated
vendored
Executable 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
114
node_modules/@hapi/accept/lib/index.d.ts
generated
vendored
Executable 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
48
node_modules/@hapi/accept/lib/index.js
generated
vendored
Executable 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
322
node_modules/@hapi/accept/lib/media.js
generated
vendored
Executable 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
38
node_modules/@hapi/accept/package.json
generated
vendored
Executable 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"
|
||||
}
|
||||
Reference in New Issue
Block a user