postman-url-encoder
Advanced tools
Comparing version 2.0.0 to 2.1.0-beta.1
@@ -210,17 +210,17 @@ /** | ||
var key = param.key, | ||
value = param.value; | ||
value = param.value, | ||
result; | ||
if (typeof key !== STRING) { | ||
key = E; | ||
if (typeof key === STRING) { | ||
result = _percentEncode(key, QUERY_ENCODE_SET); | ||
} | ||
if (typeof value !== STRING) { | ||
value = E; | ||
else { | ||
result = E; | ||
} | ||
if (key === E && value === E) { | ||
return E; | ||
if (typeof value === STRING) { | ||
result += EQUALS + _percentEncode(value, QUERY_ENCODE_SET); | ||
} | ||
return _percentEncode(key, QUERY_ENCODE_SET) + EQUALS + _percentEncode(value, QUERY_ENCODE_SET); | ||
return result; | ||
} | ||
@@ -246,7 +246,7 @@ | ||
jj, | ||
encoded, | ||
paramKey, | ||
paramKeys, | ||
paramValue, | ||
result = E; | ||
result = E, | ||
notFirstParam = false; | ||
@@ -265,6 +265,7 @@ if (!(params && typeof params === OBJECT)) { | ||
encoded = encodeQueryParam(params[i]); | ||
// don't add '&' for the very first enabled param | ||
notFirstParam && (result += AMPERSAND); | ||
notFirstParam = true; | ||
result && encoded && (result += AMPERSAND); | ||
result += encoded; | ||
result += encodeQueryParam(params[i]); | ||
} | ||
@@ -285,5 +286,7 @@ | ||
for (j = 0, jj = paramValue.length; j < jj; j++) { | ||
encoded = encodeQueryParam({ key: paramKey, value: paramValue[j] }); | ||
result && encoded && (result += AMPERSAND); | ||
result += encoded; | ||
notFirstParam && (result += AMPERSAND); | ||
notFirstParam = true; | ||
result += encodeQueryParam({ key: paramKey, value: paramValue[j] }); | ||
} | ||
@@ -293,5 +296,6 @@ } | ||
else { | ||
encoded = encodeQueryParam({ key: paramKey, value: paramValue }); | ||
result && encoded && (result += AMPERSAND); | ||
result += encoded; | ||
notFirstParam && (result += AMPERSAND); | ||
notFirstParam = true; | ||
result += encodeQueryParam({ key: paramKey, value: paramValue }); | ||
} | ||
@@ -298,0 +302,0 @@ } |
107
index.js
@@ -37,3 +37,2 @@ /** | ||
SEARCH_SEPARATOR = '#', | ||
PROTOCOL_SEPARATOR = '://', | ||
AUTH_CREDENTIALS_SEPARATOR = '@', | ||
@@ -129,19 +128,26 @@ | ||
* @param {PostmanUrl|String} url | ||
* @param {Boolean} disableEncoding | ||
* @returns {Url} | ||
*/ | ||
function toNodeUrl (url) { | ||
function toNodeUrl (url, disableEncoding) { | ||
var 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 | ||
}; | ||
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, | ||
authPassword, | ||
queryParams; | ||
@@ -158,6 +164,33 @@ // convert URL string to PostmanUrl | ||
// @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 = disableEncoding ? url.getQueryString({ ignoreDisabled: true }) : | ||
encoder.encodeQueryParams(url.query.all()); | ||
// 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; | ||
} | ||
// @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.replace(PROTOCOL_SEPARATOR, E).toLowerCase() : | ||
DEFAULT_PROTOCOL; | ||
nodeUrl.protocol = (typeof url.protocol === STRING) ? url.protocol.toLowerCase() : DEFAULT_PROTOCOL; | ||
nodeUrl.protocol += COLON; | ||
@@ -173,16 +206,19 @@ | ||
if (url.auth) { | ||
if (typeof url.auth.user === STRING) { | ||
nodeUrl.auth = encoder.encodeUserInfo(url.auth.user); | ||
if (typeof authUser === STRING) { | ||
nodeUrl.auth = disableEncoding ? authUser : encoder.encodeUserInfo(authUser); | ||
} | ||
if (typeof url.auth.password === STRING) { | ||
if (typeof authPassword === STRING) { | ||
!nodeUrl.auth && (nodeUrl.auth = E); | ||
nodeUrl.auth += COLON + encoder.encodeUserInfo(url.auth.password); | ||
nodeUrl.auth += COLON + (disableEncoding ? authPassword : encoder.encodeUserInfo(authPassword)); | ||
} | ||
// #href = protocol://user:password@ | ||
nodeUrl.auth && (nodeUrl.href += nodeUrl.auth + AUTH_CREDENTIALS_SEPARATOR); | ||
if (typeof nodeUrl.auth === STRING) { | ||
// #href = protocol://user:password@ | ||
nodeUrl.href += nodeUrl.auth + AUTH_CREDENTIALS_SEPARATOR; | ||
} | ||
} | ||
// #host, #hostname | ||
nodeUrl.host = nodeUrl.hostname = encoder.encodeHost(url.getHost()).toLowerCase(); | ||
nodeUrl.host = nodeUrl.hostname = encoder.encodeHost(hostname); // @note always encode hostname | ||
@@ -192,16 +228,15 @@ // #href = protocol://user:password@host.name | ||
// @todo Add helper in SDK to normalize port | ||
if (typeof (url.port && url.port.toString) === FUNCTION) { | ||
// #port | ||
nodeUrl.port = url.port.toString(); | ||
// #port | ||
if (typeof port === STRING) { | ||
nodeUrl.port = port; | ||
// #host = (#hostname):(#port) | ||
nodeUrl.host = nodeUrl.hostname + COLON + nodeUrl.port; | ||
nodeUrl.host = nodeUrl.hostname + COLON + port; | ||
// #href = protocol://user:password@host.name:port | ||
nodeUrl.href += COLON + nodeUrl.port; | ||
nodeUrl.href += COLON + port; | ||
} | ||
// #path, #pathname | ||
nodeUrl.path = nodeUrl.pathname = encoder.encodePath(url.getPath()); | ||
nodeUrl.path = nodeUrl.pathname = disableEncoding ? pathname : encoder.encodePath(pathname); | ||
@@ -211,5 +246,5 @@ // #href = protocol://user:password@host.name:port/p/a/t/h | ||
if (url.query.count()) { | ||
if (typeof queryParams === STRING) { | ||
// #query | ||
nodeUrl.query = encoder.encodeQueryParams(url.query.all()); | ||
nodeUrl.query = queryParams; | ||
@@ -226,5 +261,5 @@ // #search | ||
if (url.hash) { | ||
if (typeof url.hash === STRING) { | ||
// #hash | ||
nodeUrl.hash = SEARCH_SEPARATOR + encoder.encodeFragment(url.hash); | ||
nodeUrl.hash = SEARCH_SEPARATOR + (disableEncoding ? url.hash : encoder.encodeFragment(url.hash)); | ||
@@ -231,0 +266,0 @@ // #href = protocol://user:password@host.name:port/p/a/t/h?q=query#hash |
@@ -5,3 +5,3 @@ { | ||
"author": "Postman Labs <help@getpostman.com>", | ||
"version": "2.0.0", | ||
"version": "2.1.0-beta.1", | ||
"license": "Apache-2.0", | ||
@@ -31,3 +31,3 @@ "keywords": [ | ||
"dependencies": { | ||
"postman-collection": "^3.5.5", | ||
"postman-collection": "3.6.0-beta.2", | ||
"punycode": "^2.1.1" | ||
@@ -34,0 +34,0 @@ }, |
@@ -280,6 +280,22 @@ const expect = require('chai').expect, | ||
it('should handle param object with null key', function () { | ||
expect(encoder.encodeQueryParam({ key: null, value: 'bar' })).to.eql('=bar'); | ||
}); | ||
it('should handle param object without value', function () { | ||
expect(encoder.encodeQueryParam({ key: 'foo' })).to.eql('foo='); | ||
expect(encoder.encodeQueryParam({ key: 'foo' })).to.eql('foo'); | ||
}); | ||
it('should handle param object with null value', function () { | ||
expect(encoder.encodeQueryParam({ key: 'foo', value: null })).to.eql('foo'); | ||
}); | ||
it('should handle param object with empty value', function () { | ||
expect(encoder.encodeQueryParam({ key: 'foo', value: '' })).to.eql('foo='); | ||
}); | ||
it('should handle param object with empty key and empty value', function () { | ||
expect(encoder.encodeQueryParam({ key: '', value: '' })).to.eql('='); | ||
}); | ||
it('should return empty string for invalid param object', function () { | ||
@@ -291,3 +307,3 @@ expect(encoder.encodeQueryParam({})).to.eql(''); | ||
it('should ignore non-string value in param object', function () { | ||
expect(encoder.encodeQueryParam({ key: 'q', value: 123 })).to.eql('q='); | ||
expect(encoder.encodeQueryParam({ key: 'q', value: 123 })).to.eql('q'); | ||
expect(encoder.encodeQueryParam({ value: true })).to.eql(''); | ||
@@ -335,2 +351,20 @@ }); | ||
it('should handle params with empty key or value', function () { | ||
expect(encoder.encodeQueryParams([ | ||
{ key: 'get', value: null }, | ||
{ key: '', value: 'bar' }, | ||
{ key: '', value: '' }, | ||
{ key: 'baz', value: '' }, | ||
{ key: null, value: null }, | ||
{ key: '', value: null } | ||
])).to.eql('get&=bar&=&baz=&&'); | ||
expect(encoder.encodeQueryParams({ '': null })).to.eql(''); | ||
expect(encoder.encodeQueryParams({ '': '' })).to.eql('='); | ||
expect(encoder.encodeQueryParams({ '': [null, null] })).to.eql('&'); | ||
expect(encoder.encodeQueryParams({ '': ['', null] })).to.eql('=&'); | ||
expect(encoder.encodeQueryParams({ '': [null, ''] })).to.eql('&='); | ||
expect(encoder.encodeQueryParams({ '': ['', ''] })).to.eql('=&='); | ||
}); | ||
it('should handle multi-valued param object', function () { | ||
@@ -359,3 +393,2 @@ expect(encoder.encodeQueryParams({ | ||
expect(encoder.encodeQueryParams(Function)).to.equal(''); | ||
expect(encoder.encodeQueryParams([Infinity, -Infinity])).to.equal(''); | ||
}); | ||
@@ -362,0 +395,0 @@ }); |
const fs = require('fs'), | ||
path = require('path'), | ||
expect = require('chai').expect, | ||
NodeUrl = require('url'), | ||
PostmanUrl = require('postman-collection').Url, | ||
@@ -70,2 +71,23 @@ parseCsv = require('@postman/csv-parse/lib/sync'), | ||
it('should return same result as Node.js url.parse', function () { | ||
[ | ||
'http://localhost', | ||
'https://localhost/', | ||
'https://localhost?', | ||
'https://localhost?&', | ||
'https://localhost#', | ||
'https://localhost/p/a/t/h', | ||
'https://localhost/p/a/t/h?q=a&&b??c#123#321', | ||
'http://郵便屋さん.com', | ||
'http://user:password@example.com:8080/p/a/t/h?q1=v1&q2=v2#hash', | ||
'HTTP://example.com', | ||
'http://xn--48jwgn17gdel797d.com', | ||
'http://xn--iñvalid.com', | ||
'http://192.168.0.1:8080', | ||
'http://192.168.0.1' | ||
].forEach(function (url) { | ||
expect(NodeUrl.parse(url), url).to.deep.include(toNodeUrl(url)); | ||
}); | ||
}); | ||
it('should return empty url object on invalid input types', function () { | ||
@@ -97,2 +119,60 @@ var defaultUrl = { | ||
describe('with disableEncoding: true', function () { | ||
it('should always encode hostname', function () { | ||
expect(toNodeUrl('😎.cool', true)) | ||
.to.include({ | ||
host: 'xn--s28h.cool', | ||
hostname: 'xn--s28h.cool', | ||
href: 'http://xn--s28h.cool/' | ||
}); | ||
}); | ||
it('should not encode URL segments', function () { | ||
expect(toNodeUrl('r@@t:b:a:r@郵便屋さん.com:399/foo&bar/{baz}?q=("foo")#`hash`', true)) | ||
.to.eql({ | ||
protocol: 'http:', | ||
slashes: true, | ||
auth: 'r@@t:b:a:r', | ||
host: 'xn--48jwgn17gdel797d.com:399', | ||
port: '399', | ||
hostname: 'xn--48jwgn17gdel797d.com', | ||
hash: '#`hash`', | ||
search: '?q=("foo")', | ||
query: 'q=("foo")', | ||
pathname: '/foo&bar/{baz}', | ||
path: '/foo&bar/{baz}?q=("foo")', | ||
href: 'http://r@@t:b:a:r@xn--48jwgn17gdel797d.com:399/foo&bar/{baz}?q=("foo")#`hash`' | ||
}); | ||
}); | ||
// @note tests sdk.url.getQueryString code path | ||
it('should handle empty key or empty value', function () { | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
query: [ | ||
{ key: '("foo")' }, | ||
{ value: '"bar"' }, | ||
{ key: '', value: '' }, | ||
{ key: 'BAZ', value: '' }, | ||
{ key: '', value: '{qux}' } | ||
] | ||
}), true)).to.include({ | ||
query: '("foo")&="bar"&=&BAZ=&={qux}', | ||
search: '?("foo")&="bar"&=&BAZ=&={qux}' | ||
}); | ||
expect(toNodeUrl('http://localhost?', true)).to.include({ | ||
query: '', | ||
search: '?', | ||
href: 'http://localhost/?' | ||
}); | ||
expect(toNodeUrl(new PostmanUrl('localhost?&'), true)).to.include({ | ||
query: '&', | ||
search: '?&', | ||
href: 'http://localhost/?&' | ||
}); | ||
}); | ||
}); | ||
describe('PROPERTY', function () { | ||
@@ -163,5 +243,18 @@ describe('.protocol', function () { | ||
it('should handle multiple : and @ in auth', function () { | ||
expect(toNodeUrl('http://us@r:p@ssword@localhost')) | ||
.to.have.property('auth', 'us%40r:p%40ssword'); | ||
expect(toNodeUrl('http://user:p:a:s:s@localhost')) | ||
.to.have.property('auth', 'user:p%3Aa%3As%3As'); | ||
}); | ||
it('should ignore the empty and non-string username', function () { | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
auth: {} | ||
}))).to.have.property('auth', null); | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
auth: { | ||
@@ -201,2 +294,30 @@ user: ['root'], | ||
}); | ||
it('should retain @ in auth without user and password', function () { | ||
expect(toNodeUrl('http://@localhost')).to.include({ | ||
auth: '', | ||
href: 'http://@localhost/' | ||
}); | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
auth: { | ||
user: '' | ||
} | ||
}))).to.have.property('auth', ''); | ||
}); | ||
it('should retain : in auth with empty user and password', function () { | ||
expect(toNodeUrl('http://:@localhost')).to.include({ | ||
auth: ':', | ||
href: 'http://:@localhost/' | ||
}); | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
auth: { | ||
password: '' | ||
} | ||
}))).to.have.property('auth', ':'); | ||
}); | ||
}); | ||
@@ -271,3 +392,3 @@ | ||
host: 'xn:', | ||
hostname: 'xn:' | ||
hostname: 'xn' | ||
}); | ||
@@ -311,2 +432,16 @@ | ||
}); | ||
it('should accept port object which implements toString', function () { | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
port: new Number(8081) // eslint-disable-line no-new-wrappers | ||
}))).to.have.property('port', '8081'); | ||
}); | ||
it('should retain : in empty port', function () { | ||
expect(toNodeUrl('http://localhost:')).to.include({ | ||
port: '', | ||
href: 'http://localhost:/' | ||
}); | ||
}); | ||
}); | ||
@@ -338,2 +473,9 @@ | ||
}); | ||
it('should retain # in empty hash', function () { | ||
expect(toNodeUrl('http://localhost#')).to.include({ | ||
hash: '#', | ||
href: 'http://localhost/#' | ||
}); | ||
}); | ||
}); | ||
@@ -380,6 +522,15 @@ | ||
host: 'example.com', | ||
query: [' ', '"', '#', '&', '\'', '<', '=', '>'] | ||
query: [ | ||
{ key: ' ' }, | ||
{ key: '"' }, | ||
{ key: '#' }, | ||
{ key: '&' }, | ||
{ key: '\'' }, | ||
{ key: '<' }, | ||
{ key: '=' }, | ||
{ key: '>' } | ||
] | ||
}))).to.include({ | ||
query: '%20=&%22=&%23=&%26=&%27=&%3C=&%3E=', | ||
search: '?%20=&%22=&%23=&%26=&%27=&%3C=&%3E=' | ||
query: '%20&%22&%23&%26&%27&%3C&%3D&%3E', | ||
search: '?%20&%22&%23&%26&%27&%3C&%3D&%3E' | ||
}); | ||
@@ -394,5 +545,49 @@ }); | ||
}); | ||
it('should handle empty key or empty value', function () { | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
query: [ | ||
{ key: 'foo' }, | ||
{ value: 'Bar' }, | ||
{ key: '', value: '' }, | ||
{ key: 'BAZ', value: '' }, | ||
{ key: '', value: 'QuX' } | ||
] | ||
}))).to.include({ | ||
query: 'foo&=Bar&=&BAZ=&=QuX', | ||
search: '?foo&=Bar&=&BAZ=&=QuX' | ||
}); | ||
}); | ||
it('should not include disabled params', function () { | ||
expect(toNodeUrl(new PostmanUrl({ | ||
host: 'example.com', | ||
query: [ | ||
{ key: 'foo', value: 'bar', disabled: true } | ||
] | ||
}))).to.include({ | ||
query: null, | ||
search: null, | ||
href: 'http://example.com/' | ||
}); | ||
}); | ||
it('should retain ? in empty query param', function () { | ||
expect(toNodeUrl('http://localhost?')).to.include({ | ||
query: '', | ||
search: '?', | ||
href: 'http://localhost/?' | ||
}); | ||
expect(toNodeUrl(new PostmanUrl('localhost?&'))).to.include({ | ||
query: '&', | ||
search: '?&', | ||
href: 'http://localhost/?&' | ||
}); | ||
}); | ||
}); | ||
describe('.path and pathname', function () { | ||
// @note this is similar to Node.js (new URL) API | ||
it('should be `/` if path is absent', function () { | ||
@@ -399,0 +594,0 @@ expect(toNodeUrl(new PostmanUrl({ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
159963
3496
0
1
+ Addedfaker@4.1.0(transitive)
+ Addediconv-lite@0.5.1(transitive)
+ Addedlodash@4.17.15(transitive)
+ Addedmarked@0.8.0(transitive)
+ Addedmime-db@1.43.0(transitive)
+ Addedmime-format@2.0.0(transitive)
+ Addedmime-types@2.1.26(transitive)
+ Addedpostman-collection@3.6.0-beta.2(transitive)
+ Addedpostman-url-encoder@2.0.0(transitive)
+ Addedsemver@7.1.3(transitive)