feat: Created a mini nodeJS server with NewMan for testing without PostMan GUI.

This will mimic a run in a CD/CI environment or docker container.
This commit is contained in:
Simon Priet
2021-09-08 14:01:19 +02:00
parent 5fbd7c88fa
commit e69a613a37
5610 changed files with 740417 additions and 3 deletions

136
node_modules/postman-url-encoder/CHANGELOG.yaml generated vendored Normal file
View File

@@ -0,0 +1,136 @@
3.0.5:
date: 2021-08-16
fixed bugs:
- Fixed a bug where `encoder.encodeHost` throws in the browser
chores:
- Setup browser tests
3.0.4:
date: 2021-08-09
fixed bugs:
- Fixed a bug where leading slashes are trimmed incorrectly
chores:
- Removed punycode fallback for Electron v3
- Updated dependencies
3.0.3:
date: 2021-07-25
fixed bugs:
- >-
GH-133 Fixed a bug where slashes in the `file` protocol are handled
incorrectly
3.0.2:
date: 2021-07-14
fixed bugs:
- >-
GH-130 Fixed a bug where extra slashes and backslashes in the protocol are
not handled correctly
chores:
- Added secure codecov publish script
- Updated dependencies
3.0.1:
date: 2021-01-02
chores:
- Updated dependencies
3.0.0:
date: 2020-10-04
new features:
- GH-48 Added URL parser module
breaking changes:
- GH-49 Dropped support for Node < v10
chores:
- GH-50 Convert EncodeSet to ES6 class
- GH-52 Automated releases and publish process
- GH-51 Automated gh-pages docs deployment
- >-
GH-49 Updated .npmignore to prevent the addition of tests and config files
in the published package
- GH-49 Added system test
- GH-49 Moved postman-collection to dev-dependencies
- GH-49 Updated nyc configuration
- GH-49 Updated ESLint rules
- GH-49 Updated dependencies
2.1.3:
date: 2020-07-29
fixed bugs:
- >-
GH-41 Fixed a bug where square brackets are not removed from IPv6 hostname
on `toNodeURL()`
chores:
- Updated dependencies
2.1.2:
date: 2020-07-13
chores:
- Updated dependencies
2.1.1:
date: 2020-03-15
fixed bugs:
- GH-20 Removed `&` and `=` from QUERY_ENCODE_SET
2.1.0:
date: 2020-03-02
new features:
- GH-11 Added an option to disable encoding on `toNodeUrl()`
- >-
GH-13 Added `resolveNodeUrl()` method to resolve target URL relative to a
base URL
fixed bugs:
- >-
GH-12 Fixed a bug where Node.js native `url.domainToASCII` was not working
as expected in Electron v3
- GH-10 Handle query parameters with empty key or value
- >-
GH-9 Fixed a bug where query params without value were changed to params
with empty value while encoding single param
2.0.0:
date: 2020-02-06
new features:
- Implementation of the WHATWG URL Standard
- Introduces new `/encoder` module with various encoding helpers
- Method `toNodeUrl()` now follows the WHATWG URL standard for encoding
breaking changes:
- Renamed legacy `toNodeUrl()` method to `toLegacyNodeUrl()`
- |
Changed `encode()` function to encode SPACE, ("), (#), (&), ('), (<),
(=), and (>). In previous versions, it was encoding SPACE, (!), ("), ((),
()), (<), (>), (%), ('), and (*).
- Deprecated `toLegacyNodeUrl()` in favor of `toNodeUrl()`
- Deprecated `encode()` in favor of `encodeQueryParam()`
- |
Dropped support for following methods:
-> percentEncode()
-> isPreEncoded()
-> isPreEncodedCharacter()
-> charactersToPercentEncode()
chores:
- Updated dependencies
- Update license from MIT to Apache-2.0
1.0.3:
date: 2019-10-16
chores:
- Updated dependencies
1.0.2:
date: 2019-04-08
new features:
- >-
Added `toNodeUrl()` function to convert a string URL into Node's URL type
object
1.0.1:
date: 2017-02-01
chore:
- Updated package.json
1.0.0:
date: 2017-02-01
initial release:
- Initial Release

176
node_modules/postman-url-encoder/LICENSE.md generated vendored Normal file
View File

@@ -0,0 +1,176 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

49
node_modules/postman-url-encoder/README.md generated vendored Normal file
View File

@@ -0,0 +1,49 @@
# Postman URL Encoder [![Build Status](https://travis-ci.com/postmanlabs/postman-url-encoder.svg?branch=develop)](https://travis-ci.com/postmanlabs/postman-url-encoder) [![codecov](https://codecov.io/gh/postmanlabs/postman-url-encoder/branch/develop/graph/badge.svg)](https://codecov.io/gh/postmanlabs/postman-url-encoder)
Postman URL Encoder is a NodeJS module that provides various URL encoding related APIs. This module is created to
implement the [WHATWG URL specification](https://url.spec.whatwg.org/) to remove dependency on Node's URL APIs across
Postman systems. These APIs are useful to encode different parts (like hostname, path, query) of URL and convert
[PostmanUrl](http://www.postmanlabs.com/postman-collection/Url.html) object into
[Node's Url](https://nodejs.org/dist/latest-v10.x/docs/api/url.html#url_legacy_urlobject) like object.
## Installing the Postman URL Encoder
Postman URL Encoder can be installed using NPM or directly from the git repository within your NodeJS projects. If
installing from NPM, the following command installs the module and saves in your `package.json`
```terminal
> npm install postman-url-encoder --save
```
## Getting Started
Following example snippet shows how to convert [PostmanUrl](http://www.postmanlabs.com/postman-collection/Url.html)
object into [Node's Url](https://nodejs.org/dist/latest-v10.x/docs/api/url.html#url_legacy_urlobject) like object.
```javascript
var PostmanUrl = require('postman-collection').Url,
pmEncoder = require('postman-url-encoder'),
myUrl;
// Create PostmanUrl object
myUrl = new PostmanUrl('http://example.com/p/a/t/h?q1=v1');
// convert PostmanUrl object to Node's Url like object
myUrl = pmEncoder.toNodeUrl(myUrl));
// {
// protocol: 'http:',
// slashes: true,
// auth: null,
// host: 'example.com',
// port: null,
// hostname: 'example.com',
// hash: null,
// search: '?q1=v1',
// query: 'q1=v1',
// pathname: '/p/a/t/h',
// path: '/p/a/t/h?q1=v1',
// href: 'http://example.com/p/a/t/h?q1=v1'
// }
```
To know more about provided APIs, head over to [Postman URL Encoder Docs](http://www.postmanlabs.com/postman-url-encoder).

341
node_modules/postman-url-encoder/encoder/encode-set.js generated vendored Normal file
View File

@@ -0,0 +1,341 @@
/**
* @fileoverview
* An EncodeSet represents a set of characters that should be percent-encoded.
*
* Different characters need to be encoded in different parts of an URL.
* For example, a literal ? question mark in an URLs path would indicate the
* start of the query string. A question mark meant to be part of the path
* therefore needs to be percent-encoded.
* In the query string however, a question mark does not have any special
* meaning and does not need to be percent-encoded.
*
* A few sets are defined in this module.
* Use the {@link EncodeSet} class to define different ones.
*
* @see {@link https://url.spec.whatwg.org/#simple-encode-set}
*/
/**
* A character (String), or character code (Number).
*
* @typedef {String|Number} Char
*/
/**
* A Set or Array of {@link Char}(s).
*
* @typedef {Set.<Char>|Array.<Char>} CharSet
*/
const QUERY_ENCODE_CHARS = [' ', '"', '#', '\'', '<', '>'],
FRAGMENT_EXTEND_CHARS = [' ', '"', '<', '>', '`'],
PATH_EXTEND_CHARS = ['#', '?', '{', '}'],
USERINFO_EXTEND_CHARS = ['/', ':', ';', '=', '@', '[', '\\', ']', '^', '|'];
/**
* Returns a number representing the UTF-16 code unit value of the character.
*
* @private
* @param {Char} char Character or character code
* @returns {Number} Character code
*/
function charCode (char) {
const code = (typeof char === 'string') ?
// get char code from string
char.charCodeAt(0) :
// or, normalize char code using double Bitwise NOT
// Refer: https://jsperf.com/truncating-decimals
~~char;
// ensure UTF-16 range [0, 0xFFFF]
return (code >= 0 && code <= 0xFFFF) ? code : 0;
}
/**
* Extends the EncodeSet with the given characters.
*
* @note Mutates the input EncodeSet.
*
* @private
* @param {EncodeSet} encodeSet Instance of EncodeSet
* @param {CharSet} chars Character set to extend
* @returns {EncodeSet} Given EncodeSet
*/
function extendEncodeSet (encodeSet, chars) {
// special handling for Uint8Array chars which signify an existing encode
// set used to extend the given encodeSet.
if (chars instanceof Uint8Array) {
// iterate over fixed / known size set
encodeSet._set.forEach((encoded, index) => {
if (!encoded && chars[index]) {
// encode charCodeAt(index)
encodeSet._set[index] = 1;
}
});
return encodeSet;
}
// check if the input characters are iterable or not
if (!(chars && typeof chars.forEach === 'function')) {
return encodeSet;
}
chars.forEach((char) => {
encodeSet.add(char);
});
return encodeSet;
}
/**
* Represents a set of characters / bytes that should be percent-encoded.
*/
class EncodeSet {
/**
* @param {CharSet} chars Character set to encode
*/
constructor (chars) {
/**
* Indexes in Uint8Array represents char codes for characters to encode.
*
* Size: 128, ASCII range [0, 0x7F]
*
* where,
* 1 -> encode
* 0 -> don't encode
*
* @private
* @type {Uint8Array}
*/
this._set = new Uint8Array(0x80);
// encode C0 control codes [00, 0x1F] AND 0x7F
this._set.fill(1, 0, 0x20); // 0 to 31
this._set[0x7F] = 1; // 127
/**
* A Boolean indicating whether or not this EncodeSet is sealed.
*
* @private
* @type {Boolean}
*/
this._sealed = false;
// extend this set with input characters
extendEncodeSet(this, chars);
}
/**
* Appends a new character to the EncodeSet.
*
* @example
* var xyzEncodeSet = new EncodeSet(['x', 'y', 'z'])
*
* xyzEncodeSet
* .add('X')
* .add(89) // Y
* .add(0x5a) // Z
*
* @param {Char} char Character or character code
* @returns {EncodeSet} Current EncodeSet
*/
add (char) {
// bail out if the EncodeSet is sealed
if (this._sealed) {
return this;
}
const code = charCode(char);
// ensure ASCII range
if (code < 0x80) {
this._set[code] = 1;
}
// chaining
return this;
}
/**
* Returns a boolean asserting whether the given char code will be encoded in
* the EncodeSet or not.
*
* @note Always encode C0 control codes in the range U+0000 to U+001F and U+007F
* Refer: https://infra.spec.whatwg.org/#c0-control
*
* @example
* var tildeEncodeSet = new EncodeSet(['~'])
*
* // returns true
* tildeEncodeSet.has('~'.charCodeAt(0))
*
* // returns false
* tildeEncodeSet.has(65) // A
*
* // returns true
* tildeEncodeSet.has(31) // \u001f (control character)
*
* @param {Number} code Character code
* @returns {Boolean} Returns true if the character with the specified char code
* exists in the EncodeSet; otherwise false
*/
has (code) {
// encode if not in ASCII range (-∞, 0) OR (127, ∞)
if (code < 0 || code > 0x7F) {
return true;
}
// encode if present in the set
return Boolean(this._set[code]);
}
/**
* Creates a copy of the current EncodeSet.
*
* @example
* var set1 = new EncodeSet(['<', '>'])
* var set1Copy = set1.clone().add('=')
*
* @returns {EncodeSet} New EncodeSet instance
*/
clone () {
return new EncodeSet(this._set);
}
/**
* Seals the current EncodeSet to prevent new characters being added to it.
*
* @example
* var set = new EncodeSet()
*
* set.add(95)
* set.has(95) // returns true
*
* set.seal()
* set.add(100)
* set.has(100) // returns false
*
* @returns {EncodeSet} Current EncodeSet
*/
seal () {
this._sealed = true;
try {
// @note Cannot freeze array buffer views with elements.
// So, rely upon the alternative `Object.seal` method and avoid mutations
// via EncodeSet~add method.
// Also, sealed Uint8Array enumerates faster in V8!
Object.seal(this._set);
}
catch (_) {
// silently swallow exceptions
}
return this;
}
/**
* Creates a new EncodeSet by extending the input EncodeSet with additional
* characters.
*
* @example
* var fooEncodeSet = new EncodeSet(['f', 'o'])
* var foobarEncodeSet = EncodeSet.extend(fooEncodeSet, new Set(['b', 'a', 'r']))
*
* @param {EncodeSet} encodeSet Instance of EncodeSet
* @param {CharSet} chars Character set to encode
* @returns {EncodeSet} Copy of given `encodeSet` with extended `chars`
* @throws {TypeError} Argument `encodeSet` must be of type {@link EncodeSet}
*/
static extend (encodeSet, chars) {
if (!EncodeSet.isEncodeSet(encodeSet)) {
throw new TypeError('Argument `encodeSet` must be EncodeSet');
}
// extend the cloned encodeSet to avoid mutations
return extendEncodeSet(encodeSet.clone(), chars);
}
/**
* Determines whether the input value is an EncodeSet or not.
*
* @example
* // returns true
* EncodeSet.isEncodeSet(new EncodeSet([40, 41]))
*
* // returns false
* EncodeSet.isEncodeSet(new Set([28, 05]))
*
* @param {*} value The value to be tested
* @returns {Boolean} true if the given value is an EncodeSet; otherwise, false
*/
static isEncodeSet (value) {
return Boolean(value) && (value instanceof EncodeSet);
}
}
const // eslint-disable-line one-var
/**
* The C0 control percent-encode set are the C0 controls and all code points
* greater than U+007E (~).
*
* @const
* @type {EncodeSet}
* @see {@link https://url.spec.whatwg.org/#c0-control-percent-encode-set}
*/
C0_CONTROL_ENCODE_SET = new EncodeSet().seal(),
/**
* The fragment percent-encode set is the C0 control percent-encode set and
* U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), and U+0060 (`).
*
* @const
* @type {EncodeSet}
* @see {@link https://url.spec.whatwg.org/#fragment-percent-encode-set}
*/
FRAGMENT_ENCODE_SET = EncodeSet.extend(C0_CONTROL_ENCODE_SET, FRAGMENT_EXTEND_CHARS).seal(),
/**
* The path percent-encode set is the fragment percent-encode set and
* U+0023 (#), U+003F (?), U+007B ({), and U+007D (}).
*
* @const
* @type {EncodeSet}
* @see {@link https://url.spec.whatwg.org/#path-percent-encode-set}
*/
PATH_ENCODE_SET = EncodeSet.extend(FRAGMENT_ENCODE_SET, PATH_EXTEND_CHARS).seal(),
/**
* The userinfo percent-encode set is the path percent-encode set and
* U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+0040 (@), U+005B ([),
* U+005C (\), U+005D (]), U+005E (^), and U+007C (|).
*
* @const
* @type {EncodeSet}
* @see {@link https://url.spec.whatwg.org/#userinfo-percent-encode-set}
*/
USERINFO_ENCODE_SET = EncodeSet.extend(PATH_ENCODE_SET, USERINFO_EXTEND_CHARS).seal(),
/**
* The query percent-encode set is the C0 control percent-encode set and
* U+0020 SPACE, U+0022 ("), U+0023 (#), U+0027 ('), U+003C (<), and U+003E (>).
*
* @const
* @type {EncodeSet}
* @see {@link https://url.spec.whatwg.org/#query-state}
*/
QUERY_ENCODE_SET = new EncodeSet(QUERY_ENCODE_CHARS).seal();
module.exports = {
// EncodeSet class
EncodeSet,
// Constants
PATH_ENCODE_SET,
QUERY_ENCODE_SET,
FRAGMENT_ENCODE_SET,
USERINFO_ENCODE_SET,
C0_CONTROL_ENCODE_SET
};

366
node_modules/postman-url-encoder/encoder/index.js generated vendored Normal file
View File

@@ -0,0 +1,366 @@
/**
* This module helps to encode different URL components and expose utility
* methods to percent-encode a given string using an {@link EncodeSet}.
*
* @example
* const encoder = require('postman-url-encoder/encoder')
*
* // returns 'xn--48jwgn17gdel797d.com'
* encoder.encodeHost('郵便屋さん.com')
*
* @example <caption>Using EncodeSet</caption>
* var EncodeSet = require('postman-url-encoder/encoder').EncodeSet
*
* var fragmentEncodeSet = new EncodeSet([' ', '"', '<', '>', '`'])
*
* // returns false
* fragmentEncodeSet.has('['.charCodeAt(0))
*
* // returns true
* fragmentEncodeSet.has('<'.charCodeAt(0))
*
* @module postman-url-encoder/encoder
* @see {@link https://url.spec.whatwg.org/#url-representation}
*/
/**
* @fileoverview
* This module determines which of the reserved characters in the different
* URL components should be percent-encoded and which can be safely used.
*
* The generic URI syntax consists of a hierarchical sequence of components
* referred to as the scheme, authority, path, query, and fragment.
*
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
*
* hier-part = "//" authority path-abempty
* / path-absolute
* / path-rootless
* / path-empty
*
* authority = [ userinfo "@" ] host [ ":" port ]
*
* @see {@link https://tools.ietf.org/html/rfc3986#section-2}
* @see {@link https://tools.ietf.org/html/rfc3986#section-3}
*/
const encodeSet = require('./encode-set'),
_percentEncode = require('./percent-encode').encode,
_percentEncodeCharCode = require('./percent-encode').encodeCharCode,
EncodeSet = encodeSet.EncodeSet,
PATH_ENCODE_SET = encodeSet.PATH_ENCODE_SET,
QUERY_ENCODE_SET = encodeSet.QUERY_ENCODE_SET,
USERINFO_ENCODE_SET = encodeSet.USERINFO_ENCODE_SET,
FRAGMENT_ENCODE_SET = encodeSet.FRAGMENT_ENCODE_SET,
C0_CONTROL_ENCODE_SET = encodeSet.C0_CONTROL_ENCODE_SET,
PARAM_VALUE_ENCODE_SET = EncodeSet.extend(QUERY_ENCODE_SET, ['&']).seal(),
PARAM_KEY_ENCODE_SET = EncodeSet.extend(QUERY_ENCODE_SET, ['&', '=']).seal(),
E = '',
EQUALS = '=',
AMPERSAND = '&',
STRING = 'string',
OBJECT = 'object',
PATH_SEPARATOR = '/',
DOMAIN_SEPARATOR = '.',
/**
* Returns the Punycode ASCII serialization of the domain.
*
* @private
* @function
* @param {String} domain domain name
* @returns {String} punycode encoded domain name
*/
domainToASCII = (function () {
// @note `url.domainToASCII` returns empty string for invalid domain.
const domainToASCII = require('url').domainToASCII;
// use faster native `url` method in Node.js
/* istanbul ignore next */
if (typeof domainToASCII === 'function') {
return domainToASCII;
}
// else, lazy load `punycode` dependency in browser
/* istanbul ignore next */
return require('punycode').toASCII;
}());
/**
* Returns the Punycode ASCII serialization of the domain.
*
* @note Returns input hostname on invalid domain.
*
* @example
* // returns 'xn--fiq228c.com'
* encodeHost('中文.com')
*
* // returns 'xn--48jwgn17gdel797d.com'
* encodeHost(['郵便屋さん', 'com'])
*
* // returns '127.0.0.1'
* encodeHost('127.1')
*
* // returns 'xn--iñvalid.com'
* encodeHost('xn--iñvalid.com')
*
* @param {String|String[]} hostName host or domain name
* @returns {String} Punycode-encoded hostname
*/
function encodeHost (hostName) {
if (Array.isArray(hostName)) {
hostName = hostName.join(DOMAIN_SEPARATOR);
}
if (typeof hostName !== STRING) {
return E;
}
// return input host name if `domainToASCII` returned an empty string
return domainToASCII(hostName) || hostName;
}
/**
* Encodes URL path or individual path segments.
*
* @example
* // returns 'foo/bar&baz'
* encodePath('foo/bar&baz')
*
* // returns 'foo/bar/%20%22%3C%3E%60%23%3F%7B%7D'
* encodePath(['foo', 'bar', ' "<>\`#?{}'])
*
* @param {String|String[]} path Path or path segments
* @returns {String} Percent-encoded path
*/
function encodePath (path) {
if (Array.isArray(path) && path.length) {
path = path.join(PATH_SEPARATOR);
}
if (typeof path !== STRING) {
return E;
}
return _percentEncode(path, PATH_ENCODE_SET);
}
/**
* Encodes URL userinfo (username / password) fields.
*
* @example
* // returns 'info~%20%22%3C%3E%60%23%3F%7B%7D%2F%3A%3B%3D%40%5B%5C%5D%5E%7C'
* encodeAuth('info~ "<>`#?{}/:;=@[\\]^|')
*
* @param {String} param Parameter to encode
* @returns {String} Percent-encoded parameter
*/
function encodeUserInfo (param) {
if (typeof param !== STRING) {
return E;
}
return _percentEncode(param, USERINFO_ENCODE_SET);
}
/**
* Encodes URL fragment identifier or hash.
*
* @example
* // returns 'fragment#%20%22%3C%3E%60'
* encodeHash('fragment# "<>`')
*
* @param {String} fragment Hash or fragment identifier to encode
* @returns {String} Percent-encoded fragment
*/
function encodeFragment (fragment) {
if (typeof fragment !== STRING) {
return E;
}
return _percentEncode(fragment, FRAGMENT_ENCODE_SET);
}
/**
* Encodes single query parameter and returns as a string.
*
* @example
* // returns 'param%20%22%23%27%3C%3E'
* encodeQueryParam('param "#\'<>')
*
* // returns 'foo=bar'
* encodeQueryParam({ key: 'foo', value: 'bar' })
*
* @param {Object|String} param Query param to encode
* @returns {String} Percent-encoded query param
*/
function encodeQueryParam (param) {
if (!param) {
return E;
}
if (typeof param === STRING) {
return _percentEncode(param, QUERY_ENCODE_SET);
}
let key = param.key,
value = param.value,
result;
if (typeof key === STRING) {
result = _percentEncode(key, PARAM_KEY_ENCODE_SET);
}
else {
result = E;
}
if (typeof value === STRING) {
result += EQUALS + _percentEncode(value, PARAM_VALUE_ENCODE_SET);
}
return result;
}
/**
* Encodes list of query parameters and returns encoded query string.
*
* @example
* // returns 'foo=bar&=foo%26bar'
* encodeQueryParams([{ key: 'foo', value: 'bar' }, { value: 'foo&bar' }])
*
* // returns 'q1=foo&q2=bar&q2=baz'
* encodeQueryParams({ q1: 'foo', q2: ['bar', 'baz'] })
*
* @param {Object|Object[]} params Query params to encode
* @returns {String} Percent-encoded query string
*/
function encodeQueryParams (params) {
let i,
j,
ii,
jj,
paramKey,
paramKeys,
paramValue,
result = E,
notFirstParam = false;
if (!(params && typeof params === OBJECT)) {
return E;
}
// handle array of query params
if (Array.isArray(params)) {
for (i = 0, ii = params.length; i < ii; i++) {
// @todo Add helper in PropertyList to filter disabled QueryParam
if (!params[i] || params[i].disabled === true) {
continue;
}
// don't add '&' for the very first enabled param
notFirstParam && (result += AMPERSAND);
notFirstParam = true;
result += encodeQueryParam(params[i]);
}
return result;
}
// handle object with query params
paramKeys = Object.keys(params);
for (i = 0, ii = paramKeys.length; i < ii; i++) {
paramKey = paramKeys[i];
paramValue = params[paramKey];
// { key: ['value1', 'value2', 'value3'] }
if (Array.isArray(paramValue)) {
for (j = 0, jj = paramValue.length; j < jj; j++) {
notFirstParam && (result += AMPERSAND);
notFirstParam = true;
result += encodeQueryParam({ key: paramKey, value: paramValue[j] });
}
}
// { key: 'value' }
else {
notFirstParam && (result += AMPERSAND);
notFirstParam = true;
result += encodeQueryParam({ key: paramKey, value: paramValue });
}
}
return result;
}
/**
* Percent-encode the given string with the given {@link EncodeSet}.
*
* @example <caption>Defaults to C0_CONTROL_ENCODE_SET</caption>
* // returns 'foo %00 bar'
* percentEncode('foo \u0000 bar')
*
* @example <caption>Encode literal @ using custom EncodeSet</caption>
* // returns 'foo%40bar'
* percentEncode('foo@bar', new EncodeSet(['@']))
*
* @param {String} value String to percent-encode
* @param {EncodeSet} [encodeSet=C0_CONTROL_ENCODE_SET] EncodeSet to use for encoding
* @returns {String} Percent-encoded string
*/
function percentEncode (value, encodeSet) {
if (!(value && typeof value === STRING)) {
return E;
}
// defaults to C0_CONTROL_ENCODE_SET
if (!EncodeSet.isEncodeSet(encodeSet)) {
encodeSet = C0_CONTROL_ENCODE_SET;
}
return _percentEncode(value, encodeSet);
}
/**
* Percent encode a character with given code.
*
* @example
* // returns '%20'
* percentEncodeCharCode(32)
*
* @param {Number} code Character code
* @returns {String} Percent-encoded character
*/
function percentEncodeCharCode (code) {
// ensure [0x00, 0xFF] range
if (!(Number.isInteger(code) && code >= 0 && code <= 0xFF)) {
return E;
}
return _percentEncodeCharCode(code);
}
module.exports = {
// URL components
encodeHost,
encodePath,
encodeUserInfo,
encodeFragment,
encodeQueryParam,
encodeQueryParams,
/** @type EncodeSet */
EncodeSet,
// Utilities
percentEncode,
percentEncodeCharCode
};

View File

@@ -0,0 +1,118 @@
/**
* This modules provides simple percent (URI) encoding.
*
* @note Safety check for input types is not done intentionally as these
* functions are invoked in the hot code path.
*
* @private
* @module postman-url-encoder/encoder/percent-encode
*/
/**
* @fileoverview
* A percent-encoding mechanism is used to represent a data octet in a component
* when that octet's corresponding character is outside the allowed set or is
* being used as a delimiter of, or within, the component.
* A percent-encoded octet is encoded as a character triplet, consisting of the
* percent character "%" followed by the two hexadecimal digits representing
* that octet's numeric value.
*
* For example, "%20" is the percent-encoding for the binary octet "00100000"
* (ABNF: %x20), which in US-ASCII corresponds to the space character (SP).
*
* @see {@link https://en.wikipedia.org/wiki/Percent-encoding}
* @see {@link https://tools.ietf.org/html/rfc3986#section-2.1}
*/
const E = '',
ZERO = '0',
PERCENT = '%';
/**
* Checks if character with given code is valid hexadecimal digit or not.
*
* @private
* @param {Number} byte Byte
* @returns {Boolean}
*/
function isPreEncodedCharacter (byte) {
return (byte >= 0x30 && byte <= 0x39) || // 0-9
(byte >= 0x41 && byte <= 0x46) || // A-F
(byte >= 0x61 && byte <= 0x66); // a-f
}
/**
* Checks if character at given index in the buffer is already percent encoded or not.
*
* @private
* @param {Buffer} buffer Buffer to check the character from
* @param {Number} i Index of the character to check
* @returns {Boolean} true if the character is encoded, false otherwise
*/
function isPreEncoded (buffer, i) {
// if it is % check next two bytes for percent encode characters
// looking for pattern %00 - %FF
return buffer[i] === 0x25 && // %
isPreEncodedCharacter(buffer[i + 1]) &&
isPreEncodedCharacter(buffer[i + 2]);
}
/**
* Percent encode a character with given code.
*
* @example
* // returns '%20'
* encodeCharCode(32)
*
* @param {Number} code Character code
* @returns {String} Percent-encoded character
*/
function encodeCharCode (code) {
let hex = code.toString(16).toUpperCase();
(hex.length === 1) && (hex = ZERO + hex);
return PERCENT + hex;
}
/**
* Percent-encode the given string with the given {@link EncodeSet}.
*
* @example
* // returns 'foo%40bar'
* encode('foo@bar', new EncodeSet(['@']))
*
* @param {String} value String to percent-encode
* @param {EncodeSet} encodeSet EncodeSet to use for encoding
* @returns {String} Percent-encoded string
*/
function encode (value, encodeSet) {
let i,
ii,
charCode,
encoded = E,
buffer = Buffer.from(value);
for (i = 0, ii = buffer.length; i < ii; ++i) {
// avoid double encoding
if (i < ii - 2 && isPreEncoded(buffer, i)) {
encoded += PERCENT + String.fromCharCode(buffer[++i], buffer[++i]);
continue;
}
charCode = buffer[i];
encoded += encodeSet.has(charCode) ?
// encode if char code present in encodeSet
encodeCharCode(charCode) :
// or, append string from char code
String.fromCharCode(charCode);
}
return encoded;
}
module.exports = {
encode,
encodeCharCode
};

447
node_modules/postman-url-encoder/index.js generated vendored Normal file
View File

@@ -0,0 +1,447 @@
/**
* Implementation of the WHATWG URL Standard.
*
* @example
* const urlEncoder = require('postman-url-encoder')
*
* // Encoding URL string to Node.js compatible Url object
* urlEncoder.toNodeUrl('郵便屋さん.com/foo&bar/{baz}?q=("foo")#`hash`')
*
* // Encoding URI component
* urlEncoder.encode('qüêry štrìng')
*
* // Encoding query string object
* urlEncoder.encodeQueryString({ q1: 'foo', q2: ['bãr', 'baž'] })
*
* @module postman-url-encoder
* @see {@link https://url.spec.whatwg.org}
*/
const querystring = require('querystring'),
legacy = require('./legacy'),
parser = require('./parser'),
encoder = require('./encoder'),
QUERY_ENCODE_SET = require('./encoder/encode-set').QUERY_ENCODE_SET,
E = '',
COLON = ':',
BACK_SLASH = '\\',
DOUBLE_SLASH = '//',
DOUBLE_BACK_SLASH = '\\\\',
STRING = 'string',
OBJECT = 'object',
FUNCTION = 'function',
DEFAULT_PROTOCOL = 'http',
LEFT_SQUARE_BRACKET = '[',
RIGHT_SQUARE_BRACKET = ']',
PATH_SEPARATOR = '/',
QUERY_SEPARATOR = '?',
PARAMS_SEPARATOR = '&',
SEARCH_SEPARATOR = '#',
DOMAIN_SEPARATOR = '.',
AUTH_CREDENTIALS_SEPARATOR = '@',
// @note this regular expression is referred from Node.js URL parser
PROTOCOL_RE = /^[a-z0-9.+-]+:(?:\/\/|\\\\)./i,
/**
* Protocols that always contain a // bit.
*
* @private
* @see {@link https://github.com/nodejs/node/blob/v10.17.0/lib/url.js#L91}
*/
SLASHED_PROTOCOLS = {
'file:': true,
'ftp:': true,
'gopher:': true,
'http:': true,
'https:': true,
'ws:': true,
'wss:': true
};
/**
* Returns stringified URL from Url object but only includes parts till given
* part name.
*
* @example
* var url = 'http://postman.com/foo?q=v#hash';
* getUrlTill(toNodeUrl(url), 'host')
* // returns 'http://postman.com'
*
* @private
* @param {Object} url base URL
* @param {String} [urlPart='query'] one of ['host', 'pathname', 'query']
*/
function getUrlTill (url, urlPart) {
let result = '';
if (url.protocol) {
result += url.protocol + DOUBLE_SLASH;
}
if (url.auth) {
result += url.auth + AUTH_CREDENTIALS_SEPARATOR;
}
result += url.host || E;
if (urlPart === 'host') { return result; }
result += url.pathname;
if (urlPart === 'pathname') { return result; }
// urlPart must be query at this point
return result + (url.search || E);
}
/**
* Percent-encode the given string using QUERY_ENCODE_SET.
*
* @deprecated since version 2.0, use {@link encodeQueryParam} instead.
*
* @example
* // returns 'foo%20%22%23%26%27%3C%3D%3E%20bar'
* encode('foo "#&\'<=> bar')
*
* // returns ''
* encode(['foobar'])
*
* @param {String} value String to percent-encode
* @returns {String} Percent-encoded string
*/
function encode (value) {
return encoder.percentEncode(value, QUERY_ENCODE_SET);
}
/**
* Percent-encode the URL query string or x-www-form-urlencoded body object
* according to RFC3986.
*
* @example
* // returns 'q1=foo&q2=bar&q2=baz'
* encodeQueryString({ q1: 'foo', q2: ['bar', 'baz'] })
*
* @param {Object} query Object representing query or urlencoded body
* @returns {String} Percent-encoded string
*/
function encodeQueryString (query) {
if (!(query && typeof query === OBJECT)) {
return E;
}
// rely upon faster querystring module
query = querystring.stringify(query);
// encode characters not encoded by querystring.stringify() according to RFC3986.
return query.replace(/[!'()*]/g, function (c) {
return encoder.percentEncodeCharCode(c.charCodeAt(0));
});
}
/**
* Converts PostmanUrl / URL string into Node.js compatible Url object.
*
* @example <caption>Using URL string</caption>
* toNodeUrl('郵便屋さん.com/foo&bar/{baz}?q=("foo")#`hash`')
* // returns
* // {
* // protocol: 'http:',
* // slashes: true,
* // auth: null,
* // host: 'xn--48jwgn17gdel797d.com',
* // port: null,
* // hostname: 'xn--48jwgn17gdel797d.com',
* // hash: '#%60hash%60',
* // search: '?q=(%22foo%22)',
* // query: 'q=(%22foo%22)',
* // pathname: '/foo&bar/%7Bbaz%7D',
* // path: '/foo&bar/%7Bbaz%7D?q=(%22foo%22)',
* // href: 'http://xn--48jwgn17gdel797d.com/foo&bar/%7Bbaz%7D?q=(%22foo%22)#%60hash%60'
* // }
*
* @example <caption>Using PostmanUrl instance</caption>
* toNodeUrl(new sdk.Url({
* host: 'example.com',
* query: [{ key: 'foo', value: 'bar & baz' }]
* }))
*
* @param {PostmanUrl|String} url URL string or PostmanUrl object
* @param {Boolean} disableEncoding Turn encoding off
* @returns {Url} Node.js like parsed and encoded object
*/
function toNodeUrl (url, disableEncoding) {
let nodeUrl = {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: null,
pathname: null,
path: null,
href: E
},
port,
hostname,
pathname,
authUser,
queryParams,
authPassword;
// Check if PostmanUrl instance and prepare segments
if (url && url.constructor && url.constructor._postman_propertyName === 'Url') {
// @note getPath() always adds a leading '/', similar to Node.js API
pathname = url.getPath();
hostname = url.getHost().toLowerCase();
if (url.query && url.query.count()) {
queryParams = url.getQueryString({ ignoreDisabled: true });
queryParams = disableEncoding ? queryParams : encoder.encodeQueryParam(queryParams);
// either all the params are disabled or a single param is like { key: '' } (http://localhost?)
// in that case, query separator ? must be included in the raw URL.
// @todo Add helper in SDK to handle this
if (queryParams === E) {
// check if there's any enabled param, if so, set queryString to empty string
// otherwise (all disabled), it will be set as undefined
queryParams = url.query.find(function (param) { return !(param && param.disabled); }) && E;
}
}
if (url.auth) {
authUser = url.auth.user;
authPassword = url.auth.password;
}
}
// Parser URL string and prepare segments
else if (typeof url === STRING) {
url = parser.parse(url);
pathname = PATH_SEPARATOR + (url.path || []).join(PATH_SEPARATOR);
hostname = (url.host || []).join(DOMAIN_SEPARATOR).toLowerCase();
queryParams = url.query && (queryParams = url.query.join(PARAMS_SEPARATOR)) &&
(disableEncoding ? queryParams : encoder.encodeQueryParam(queryParams));
authUser = (url.auth || [])[0];
authPassword = (url.auth || [])[1];
}
// bail out with empty URL object for invalid input
else {
return nodeUrl;
}
// @todo Add helper in SDK to normalize port
// eslint-disable-next-line no-eq-null, eqeqeq
if (!(url.port == null) && typeof url.port.toString === FUNCTION) {
port = url.port.toString();
}
// #protocol
nodeUrl.protocol = (typeof url.protocol === STRING) ? url.protocol.toLowerCase() : DEFAULT_PROTOCOL;
nodeUrl.protocol += COLON;
// #slashes
nodeUrl.slashes = SLASHED_PROTOCOLS[nodeUrl.protocol] || false;
// #href = protocol://
nodeUrl.href = nodeUrl.protocol + DOUBLE_SLASH;
// #auth
if (url.auth) {
if (typeof authUser === STRING) {
nodeUrl.auth = disableEncoding ? authUser : encoder.encodeUserInfo(authUser);
}
if (typeof authPassword === STRING) {
!nodeUrl.auth && (nodeUrl.auth = E);
nodeUrl.auth += COLON + (disableEncoding ? authPassword : encoder.encodeUserInfo(authPassword));
}
if (typeof nodeUrl.auth === STRING) {
// #href = protocol://user:password@
nodeUrl.href += nodeUrl.auth + AUTH_CREDENTIALS_SEPARATOR;
}
}
// #host, #hostname
nodeUrl.host = nodeUrl.hostname = hostname = encoder.encodeHost(hostname); // @note always encode hostname
// #href = protocol://user:password@host.name
nodeUrl.href += nodeUrl.hostname;
// #port
if (typeof port === STRING) {
nodeUrl.port = port;
// #host = (#hostname):(#port)
nodeUrl.host = nodeUrl.hostname + COLON + port;
// #href = protocol://user:password@host.name:port
nodeUrl.href += COLON + port;
}
// #path, #pathname
nodeUrl.path = nodeUrl.pathname = disableEncoding ? pathname : encoder.encodePath(pathname);
// #href = protocol://user:password@host.name:port/p/a/t/h
nodeUrl.href += nodeUrl.pathname;
if (typeof queryParams === STRING) {
// #query
nodeUrl.query = queryParams;
// #search
nodeUrl.search = QUERY_SEPARATOR + nodeUrl.query;
// #path = (#pathname)?(#search)
nodeUrl.path = nodeUrl.pathname + nodeUrl.search;
// #href = protocol://user:password@host.name:port/p/a/t/h?q=query
nodeUrl.href += nodeUrl.search;
}
if (typeof url.hash === STRING) {
// #hash
nodeUrl.hash = SEARCH_SEPARATOR + (disableEncoding ? url.hash : encoder.encodeFragment(url.hash));
// #href = protocol://user:password@host.name:port/p/a/t/h?q=query#hash
nodeUrl.href += nodeUrl.hash;
}
// Finally apply Node.js shenanigans
// # Remove square brackets from IPv6 #hostname
// Refer: https://github.com/nodejs/node/blob/v12.18.3/lib/url.js#L399
// Refer: https://github.com/nodejs/node/blob/v12.18.3/lib/internal/url.js#L1273
if (hostname[0] === LEFT_SQUARE_BRACKET && hostname[hostname.length - 1] === RIGHT_SQUARE_BRACKET) {
nodeUrl.hostname = hostname.slice(1, -1);
}
return nodeUrl;
}
/**
* Resolves a relative URL with respect to given base URL.
* This is a replacement method for Node's url.resolve() which is compatible
* with URL object generated by toNodeUrl().
*
* @example
* // returns 'http://postman.com/baz'
* resolveNodeUrl('http://postman.com/foo/bar', '/baz')
*
* @param {Object|String} base URL string or toNodeUrl() object
* @param {String} relative Relative URL to resolve
* @returns {String} Resolved URL
*/
function resolveNodeUrl (base, relative) {
// normalize arguments
typeof base === STRING && (base = toNodeUrl(base));
typeof relative !== STRING && (relative = E);
// bail out if base is not an object
if (!(base && typeof base === OBJECT)) {
return relative;
}
let i,
ii,
index,
baseHref,
relative_0,
relative_01,
basePathname,
requiredProps = ['protocol', 'auth', 'host', 'pathname', 'search', 'href'];
// bail out if base is not like Node url object
for (i = 0, ii = requiredProps.length; i < ii; i++) {
if (!Object.hasOwnProperty.call(base, requiredProps[i])) {
return relative;
}
}
// cache base.href and base.pathname
baseHref = base.href;
basePathname = base.pathname;
// cache relative's first two chars
relative_0 = relative.slice(0, 1);
relative_01 = relative.slice(0, 2);
// @note relative can be one of
// #1 empty string
// #2 protocol relative, starts with // or \\
// #3 path relative, starts with / or \
// #4 just query or hash, starts with ? or #
// #5 absolute URL, starts with :// or :\\
// #6 free from path, with or without query and hash
// #1 empty string
if (!relative) {
// return base as it is if there is no hash
if ((index = baseHref.indexOf(SEARCH_SEPARATOR)) === -1) {
return baseHref;
}
// else, return base without the hash
return baseHref.slice(0, index);
}
// #2 protocol relative, starts with // or \\
// @note \\ is not converted to //
if (relative_01 === DOUBLE_SLASH || relative_01 === DOUBLE_BACK_SLASH) {
return base.protocol + relative;
}
// #3 path relative, starts with / or \
// @note \(s) are not converted to /
if (relative_0 === PATH_SEPARATOR || relative_0 === BACK_SLASH) {
return getUrlTill(base, 'host') + relative;
}
// #4 just hash, starts with #
if (relative_0 === SEARCH_SEPARATOR) {
return getUrlTill(base, 'query') + relative;
}
// #4 just query, starts with ?
if (relative_0 === QUERY_SEPARATOR) {
return getUrlTill(base, 'pathname') + relative;
}
// #5 absolute URL, starts with :// or :\\
// @note :\\ is not converted to ://
if (PROTOCOL_RE.test(relative)) {
return relative;
}
// #6 free from path, with or without query and hash
// remove last path segment form base path
basePathname = basePathname.slice(0, basePathname.lastIndexOf(PATH_SEPARATOR) + 1);
return getUrlTill(base, 'host') + basePathname + relative;
}
/**
* Converts URL string into Node.js compatible Url object using the v1 encoder.
*
* @deprecated since version 2.0
*
* @param {String} url URL string
* @returns {Url} Node.js compatible Url object
*/
function toLegacyNodeUrl (url) {
return legacy.toNodeUrl(url);
}
module.exports = {
encode,
toNodeUrl,
resolveNodeUrl,
toLegacyNodeUrl,
encodeQueryString
};

242
node_modules/postman-url-encoder/legacy.js generated vendored Normal file
View File

@@ -0,0 +1,242 @@
var url = require('url'),
/**
* @private
* @const
* @type {String}
*/
E = '',
/**
* @private
* @const
* @type {String}
*/
QUERY_SEPARATOR = '?',
/**
* @private
* @const
* @type {String}
*/
AMPERSAND = '&',
/**
* @private
* @const
* @type {String}
*/
EQUALS = '=',
/**
* @private
* @const
* @type {String}
*/
PERCENT = '%',
/**
* @private
* @const
* @type {string}
*/
ZERO = '0',
/**
* @private
* @const
* @type {string}
*/
STRING = 'string',
encoder;
encoder = {
/**
* Percent encode a character with given code.
*
* @param {Number} c - character code of the character to encode
* @returns {String} - percent encoding of given character
*/
percentEncode (c) {
var hex = c.toString(16).toUpperCase();
(hex.length === 1) && (hex = ZERO + hex);
return PERCENT + hex;
},
/**
* Checks if character at given index in the buffer is already percent encoded or not.
*
* @param {Buffer} buffer -
* @param {Number} i -
* @returns {Boolean}
*/
isPreEncoded (buffer, i) {
// If it is % check next two bytes for percent encode characters
// looking for pattern %00 - %FF
return (buffer[i] === 0x25 &&
(encoder.isPreEncodedCharacter(buffer[i + 1]) &&
encoder.isPreEncodedCharacter(buffer[i + 2]))
);
},
/**
* Checks if character with given code is valid hexadecimal digit or not.
*
* @param {Number} byte -
* @returns {Boolean}
*/
isPreEncodedCharacter (byte) {
return (byte >= 0x30 && byte <= 0x39) || // 0-9
(byte >= 0x41 && byte <= 0x46) || // A-F
(byte >= 0x61 && byte <= 0x66); // a-f
},
/**
* Checks whether given character should be percent encoded or not for fixture.
*
* @param {Number} byte -
* @returns {Boolean}
*/
charactersToPercentEncode (byte) {
return (byte < 0x23 || byte > 0x7E || // Below # and after ~
byte === 0x3C || byte === 0x3E || // > and <
byte === 0x28 || byte === 0x29 || // ( and )
byte === 0x25 || // %
byte === 0x27 || // '
byte === 0x2A // *
);
},
/**
* Percent encode a query string according to RFC 3986.
* Note: This function is supposed to be used on top of node's inbuilt url encoding
* to solve issue https://github.com/nodejs/node/issues/8321
*
* @param {String} value -
* @returns {String}
*/
encode (value) {
if (!value) { return E; }
var buffer = Buffer.from(value),
ret = E,
i,
ii;
for (i = 0, ii = buffer.length; i < ii; ++i) {
if (encoder.charactersToPercentEncode(buffer[i]) && !encoder.isPreEncoded(buffer, i)) {
ret += encoder.percentEncode(buffer[i]);
}
else {
ret += String.fromCodePoint(buffer[i]); // Only works in ES6 (available in Node v4+)
}
}
return ret;
}
};
/**
* Parses a query string into an array, preserving parameter values
*
* @private
* @param {String} string -
* @returns {*}
*/
function parseQueryString (string) {
var parts;
if (typeof string === STRING) {
parts = string.split(AMPERSAND);
return parts.map(function (param, idx) {
if (param === E && idx !== (parts.length - 1)) {
return { key: null, value: null };
}
var index = (typeof param === STRING) ? param.indexOf(EQUALS) : -1,
paramObj = {};
// this means that there was no value for this key (not even blank,
// so we store this info) and the value is set to null
if (index < 0) {
paramObj.key = param.substr(0, param.length);
paramObj.value = null;
}
else {
paramObj.key = param.substr(0, index);
paramObj.value = param.substr(index + 1);
}
return paramObj;
});
}
return [];
}
/**
* Stringifies a query string, from an array of parameters
*
* @private
* @param {Object[]} parameters -
* @returns {string}
*/
function stringifyQueryParams (parameters) {
return parameters ? parameters.map(function (param) {
var key = param.key,
value = param.value;
if (value === undefined) {
return E;
}
if (key === null) {
key = E;
}
if (value === null) {
return encoder.encode(key);
}
return encoder.encode(key) + EQUALS + encoder.encode(value);
}).join(AMPERSAND) : E;
}
/**
* Converts URL string into Node's Url object with encoded values
*
* @private
* @param {String} urlString -
* @returns {Url}
*/
function toNodeUrl (urlString) {
var parsed = url.parse(urlString),
rawQs = parsed.query,
qs,
search,
path,
str;
if (!(rawQs && rawQs.length)) { return parsed; }
qs = stringifyQueryParams(parseQueryString(rawQs));
search = QUERY_SEPARATOR + qs;
path = parsed.pathname + search;
parsed.query = qs;
parsed.search = search;
parsed.path = path;
str = url.format(parsed);
// Parse again, because Node does not guarantee consistency of properties
return url.parse(str);
}
module.exports = {
toNodeUrl
};

70
node_modules/postman-url-encoder/package.json generated vendored Normal file
View File

@@ -0,0 +1,70 @@
{
"name": "postman-url-encoder",
"version": "3.0.5",
"description": "Implementation of the WHATWG URL Standard",
"author": "Postman Inc.",
"license": "Apache-2.0",
"main": "index.js",
"homepage": "https://github.com/postmanlabs/postman-url-encoder#readme",
"bugs": {
"url": "https://github.com/postmanlabs/postman-url-encoder/issues",
"email": "help@postman.com"
},
"repository": {
"type": "git",
"url": "git+https://github.com/postmanlabs/postman-url-encoder.git"
},
"keywords": [
"postman",
"url-encoder",
"url-parser",
"whatwg-url"
],
"scripts": {
"build-docs": "node npm/build-docs.js",
"codecov": "node npm/publish-coverage.js",
"release": "node npm/create-release.js",
"test": "npm run test-lint && npm run test-unit && npm run test-browser",
"test-benchmark": "node npm/test-benchmark.js",
"test-browser": "node npm/test-browser.js",
"test-lint": "node npm/test-lint.js",
"test-system": "node npm/test-system.js",
"test-unit": "nyc --nycrc-path=.nycrc.js node npm/test-unit.js"
},
"dependencies": {
"punycode": "^2.1.1"
},
"devDependencies": {
"@postman/csv-parse": "^4.0.2",
"@postman/shipit": "^0.3.0",
"async": "^3.2.1",
"bipbip": "^0.4.2",
"browserify": "^17.0.0",
"chai": "^4.3.4",
"chalk": "^4.1.2",
"colors": "^1.4.0",
"editorconfig": "^0.15.3",
"eslint": "^7.32.0",
"eslint-plugin-jsdoc": "^36.0.7",
"eslint-plugin-lodash": "^7.3.0",
"eslint-plugin-mocha": "^9.0.0",
"eslint-plugin-security": "^1.4.0",
"jsdoc": "^3.6.7",
"karma": "^6.3.4",
"karma-browserify": "^8.1.0",
"karma-chrome-launcher": "^3.1.0",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"mocha": "^9.0.3",
"nyc": "^15.1.0",
"parse-gitignore": "^1.0.1",
"postman-collection": "^4.0.2",
"postman-jsdoc-theme": "^0.0.3",
"recursive-readdir": "^2.2.2",
"shelljs": "^0.8.3",
"watchify": "^4.0.0"
},
"engines": {
"node": ">=10"
}
}

293
node_modules/postman-url-encoder/parser/index.js generated vendored Normal file
View File

@@ -0,0 +1,293 @@
/**
* This module helps to break URL strings up into components
* (protocol, auth, host, port, path, query, and hash) keeping the variables
* intact.
*
* @example
* const parser = require('postman-url-encoder/parser')
*
* // returns
* // {
* // raw: 'protocol://{{user}}:{{p@ssw?rd}}@{{host.name}}.com:{{#port}}/p/a/t/h?q=query#hash',
* // protocol: 'protocol',
* // auth: [ '{{user}}', '{{p@ssw?rd}}' ],
* // host: [ '{{host.name}}', 'com' ],
* // port: '{{#port}}',
* // path: [ 'p', 'a', 't', 'h' ],
* // query: [ 'q=query' ],
* // hash: 'hash'
* // }
* parser.parse('protocol://{{user}}:{{p@ssw?rd}}@{{host.name}}.com:{{#port}}/p/a/t/h?q=query#hash')
*
* @module postman-url-encoder/parser
*/
const ReplacementTracker = require('./replacement-tracker'),
REGEX_ALL_BACKSLASHES = /\\/g,
REGEX_LEADING_SLASHES = /^\/+/,
REGEX_ALL_VARIABLES = /{{[^{}]*[.:/?#@&\]][^{}]*}}/g,
HASH_SEPARATOR = '#',
PATH_SEPARATOR = '/',
PORT_SEPARATOR = ':',
AUTH_SEPARATOR = '@',
QUERY_SEPARATOR = '?',
DOMAIN_SEPARATOR = '.',
PROTOCOL_SEPARATOR = '://',
AUTH_SEGMENTS_SEPARATOR = ':',
QUERY_SEGMENTS_SEPARATOR = '&',
E = '',
STRING = 'string',
FILE_PROTOCOL = 'file',
SAFE_REPLACE_CHAR = '_',
CLOSING_SQUARE_BRACKET = ']',
URL_PROPERTIES_ORDER = ['protocol', 'auth', 'host', 'port', 'path', 'query', 'hash'];
/**
* Normalize the given string by replacing the variables which includes
* reserved characters in its name.
* The replaced characters are added to the given replacement tracker instance.
*
* @private
* @param {String} str String to normalize
* @param {ReplacementTracker} replacements ReplacementTracker instance
* @returns {String} Normalized string
*/
function normalizeVariables (str, replacements) {
let normalizedString = E,
pointer = 0, // pointer till witch the string is normalized
variable,
match,
index;
// find all the instances of {{<variable>}} which includes reserved chars
// "Hello {{user#name}}!!!"
// ↑ (pointer = 0)
while ((match = REGEX_ALL_VARIABLES.exec(str)) !== null) {
// {{user#name}}
variable = match[0];
// starting index of the {{variable}} in the string
// "Hello {{user#name}}!!!"
// ↑ (index = 6)
index = match.index;
// [pointer, index) string is normalized + the safe replacement character
// "Hello " + "_"
normalizedString += str.slice(pointer, index) + SAFE_REPLACE_CHAR;
// track the replacement done for the {{variable}}
replacements.add(variable, index);
// update the pointer
// "Hello {{user#name}}!!!"
// ↑ (pointer = 19)
pointer = index + variable.length;
}
// avoid slicing the string in case of no matches
if (pointer === 0) {
return str;
}
// whatever left in the string is normalized as well
/* istanbul ignore else */
if (pointer < str.length) {
// "Hello _" + "!!!"
normalizedString += str.slice(pointer);
}
return normalizedString;
}
/**
* Update replaced characters in the URL object with its original value.
*
* @private
* @param {Object} url URL tracker object
* @param {ReplacementTracker} replacements ReplacementTracker instance
*/
function applyReplacements (url, replacements) {
let i,
ii,
prop;
// traverse each URL property in the given order
for (i = 0, ii = URL_PROPERTIES_ORDER.length; i < ii; ++i) {
prop = url[URL_PROPERTIES_ORDER[i]];
// bail out if the given property is not set (undefined or '')
if (!(prop && prop.value)) {
continue;
}
prop.value = replacements.apply(prop.value, prop.beginIndex, prop.endIndex);
}
return url;
}
/**
* Parses the input string by decomposing the URL into constituent parts,
* such as path, host, port, etc.
*
* @param {String} urlString The URL string to parse
* @returns {Object} Parsed URL object
*/
function parse (urlString) {
let url = {
protocol: { value: undefined, beginIndex: 0, endIndex: 0 },
auth: { value: undefined, beginIndex: 0, endIndex: 0 },
host: { value: undefined, beginIndex: 0, endIndex: 0 },
port: { value: undefined, beginIndex: 0, endIndex: 0 },
path: { value: undefined, beginIndex: 0, endIndex: 0 },
query: { value: undefined, beginIndex: 0, endIndex: 0 },
hash: { value: undefined, beginIndex: 0, endIndex: 0 }
},
parsedUrl = {
raw: urlString,
protocol: undefined,
auth: undefined,
host: undefined,
port: undefined,
path: undefined,
query: undefined,
hash: undefined
},
replacements = new ReplacementTracker(),
pointer = 0,
_length,
length,
index,
port;
// bail out if input string is empty
if (!(urlString && typeof urlString === STRING)) {
return parsedUrl;
}
// trim leading whitespace characters
parsedUrl.raw = urlString = urlString.trimLeft();
// normalize the given string
urlString = normalizeVariables(urlString, replacements);
length = urlString.length;
// 1. url.hash
if ((index = urlString.indexOf(HASH_SEPARATOR)) !== -1) {
// extract from the back
url.hash.value = urlString.slice(index + 1);
url.hash.beginIndex = pointer + index + 1;
url.hash.endIndex = pointer + length;
urlString = urlString.slice(0, (length = index));
}
// 2. url.query
if ((index = urlString.indexOf(QUERY_SEPARATOR)) !== -1) {
// extract from the back
url.query.value = urlString.slice(index + 1).split(QUERY_SEGMENTS_SEPARATOR);
url.query.beginIndex = pointer + index + 1;
url.query.endIndex = pointer + length;
urlString = urlString.slice(0, (length = index));
}
// 3. url.protocol
urlString = urlString.replace(REGEX_ALL_BACKSLASHES, PATH_SEPARATOR); // sanitize slashes
// @todo support `protocol:host/path` and `protocol:/host/path`
if ((index = urlString.indexOf(PROTOCOL_SEPARATOR)) !== -1) {
// extract from the front
url.protocol.value = urlString.slice(0, index);
url.protocol.beginIndex = pointer;
url.protocol.endIndex = pointer + index;
urlString = urlString.slice(index + 3);
length -= index + 3;
pointer += index + 3;
// special handling for extra slashes in protocol e.g, http:///example.com
_length = length; // length with leading slashes
urlString = urlString.replace(REGEX_LEADING_SLASHES,
(url.protocol.value.toLowerCase() === FILE_PROTOCOL) ?
// file:////path -> file:///path
PATH_SEPARATOR :
// protocol:////host/path -> protocol://host/path
E);
length = urlString.length; // length without slashes
pointer += _length - length; // update pointer
}
// 4. url.path
if ((index = urlString.indexOf(PATH_SEPARATOR)) !== -1) {
// extract from the back
url.path.value = urlString.slice(index + 1).split(PATH_SEPARATOR);
url.path.beginIndex = pointer + index + 1;
url.path.endIndex = pointer + length;
urlString = urlString.slice(0, (length = index));
}
// 5. url.auth
if ((index = urlString.lastIndexOf(AUTH_SEPARATOR)) !== -1) {
// extract from the front
url.auth.value = urlString.slice(0, index);
url.auth.beginIndex = pointer;
url.auth.endIndex = pointer + index;
urlString = urlString.slice(index + 1);
length -= index + 1;
pointer += index + 1;
// separate username:password
if ((index = url.auth.value.indexOf(AUTH_SEGMENTS_SEPARATOR)) !== -1) {
url.auth.value = [url.auth.value.slice(0, index), url.auth.value.slice(index + 1)];
}
else {
url.auth.value = [url.auth.value];
}
}
// 6. url.port
if ((index = urlString.lastIndexOf(PORT_SEPARATOR)) !== -1 &&
// eslint-disable-next-line lodash/prefer-includes
(port = urlString.slice(index + 1)).indexOf(CLOSING_SQUARE_BRACKET) === -1
) {
// extract from the back
url.port.value = port;
url.port.beginIndex = pointer + index + 1;
url.port.endIndex = pointer + length;
urlString = urlString.slice(0, (length = index));
}
// 7. url.host
if (urlString) {
url.host.value = urlString.split(DOMAIN_SEPARATOR);
url.host.beginIndex = pointer;
url.host.endIndex = pointer + length;
}
// apply replacements back, if any
replacements.count() && applyReplacements(url, replacements);
// finally, prepare parsed url
parsedUrl.protocol = url.protocol.value;
parsedUrl.auth = url.auth.value;
parsedUrl.host = url.host.value;
parsedUrl.port = url.port.value;
parsedUrl.path = url.path.value;
parsedUrl.query = url.query.value;
parsedUrl.hash = url.hash.value;
return parsedUrl;
}
module.exports = {
parse
};

View File

@@ -0,0 +1,151 @@
/**
* Tracks replacements done on a string and expose utility to patch replacements.
*
* @note due to performance reasons, it doesn't store the original string or
* perform ops on the string.
*
* @private
* @constructor
*/
class ReplacementTracker {
constructor () {
this.replacements = [];
this._offset = 0;
this._length = 0;
}
/**
* Add new replacement to track.
*
* @param {String} value -
* @param {Number} index -
*/
add (value, index) {
this.replacements.push({
value: value,
index: index - this._offset
});
this._offset += value.length - 1; // - 1 replaced character
this._length++;
}
/**
* Returns the total number of replacements.
*
* @returns {Number}
*/
count () {
return this._length;
}
/**
* Finds the lower index of replacement position for a given value using inexact
* binary search.
*
* @private
* @param {Number} index -
* @returns {Number}
*/
_findLowerIndex (index) {
let length = this.count(),
start = 0,
end = length - 1,
mid;
while (start <= end) {
mid = (start + end) >> 1; // divide by 2
if (this.replacements[mid].index >= index) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
return start >= length ? -1 : start;
}
/**
* Patches a given string by apply all the applicable replacements done in the
* given range.
*
* @private
* @param {String} input -
* @param {Number} beginIndex -
* @param {Number} endIndex -
* @returns {String}
*/
_applyInString (input, beginIndex, endIndex) {
let index,
replacement,
replacementIndex,
replacementValue,
offset = 0,
length = this.count();
// bail out if no replacements are done in the given range OR empty string
if (!input || (index = this._findLowerIndex(beginIndex)) === -1) {
return input;
}
do {
replacement = this.replacements[index];
replacementIndex = replacement.index;
replacementValue = replacement.value;
// bail out if all the replacements are done in the given range
if (replacementIndex >= endIndex) {
break;
}
replacementIndex = offset + replacementIndex - beginIndex;
input = input.slice(0, replacementIndex) + replacementValue + input.slice(replacementIndex + 1);
offset += replacementValue.length - 1;
} while (++index < length);
return input;
}
/**
* Patches a given string or array of strings by apply all the applicable
* replacements done in the given range.
*
* @param {String|String[]} input -
* @param {Number} beginIndex -
* @param {Number} endIndex -
* @returns {String|String[]}
*/
apply (input, beginIndex, endIndex) {
let i,
ii,
length,
_endIndex,
_beginIndex,
value = input;
// apply replacements in string
if (typeof input === 'string') {
return this._applyInString(input, beginIndex, endIndex);
}
// apply replacements in the splitted string (Array)
_beginIndex = beginIndex;
// traverse all the segments until all the replacements are patched
for (i = 0, ii = input.length; i < ii; ++i) {
value = input[i];
_endIndex = _beginIndex + (length = value.length);
// apply replacements applicable for individual segment
input[i] = this._applyInString(value, _beginIndex, _endIndex);
_beginIndex += length + 1; // + 1 separator
}
return input;
}
}
module.exports = ReplacementTracker;