postman-url-encoder
Advanced tools
Comparing version 1.0.1 to 1.0.2
211
index.js
@@ -1,2 +0,4 @@ | ||
var /** | ||
var url = require('url'), | ||
/** | ||
* @private | ||
@@ -6,2 +8,30 @@ * @const | ||
*/ | ||
E = '', | ||
/** | ||
* @private | ||
* @const | ||
* @type {String} | ||
*/ | ||
QUERY_SEPARATOR = '?', | ||
/** | ||
* @private | ||
* @const | ||
* @type {String} | ||
*/ | ||
AMPERSAND = '&', | ||
/** | ||
* @private | ||
* @const | ||
* @type {String} | ||
*/ | ||
EQUALS = '=', | ||
/** | ||
* @private | ||
* @const | ||
* @type {String} | ||
*/ | ||
PERCENT = '%', | ||
@@ -14,6 +44,91 @@ | ||
*/ | ||
ZERO = '0'; | ||
ZERO = '0', | ||
module.exports = { | ||
/** | ||
* @private | ||
* @const | ||
* @type {string} | ||
*/ | ||
STRING = 'string', | ||
parseQueryString, | ||
stringifyQueryParams, | ||
encoder; | ||
/** | ||
* Parses a query string into an array, preserving parameter values | ||
* Note: This function is temporary. It will be removed once we implement our own encoding | ||
* instead of url.parse(). | ||
* | ||
* @param string | ||
* @returns {*} | ||
*/ | ||
parseQueryString = function (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 | ||
* Note: This function is temporary. It will be removed once we implement our own encoding | ||
* instead of url.parse(). | ||
* | ||
* @param parameters | ||
* @returns {string} | ||
*/ | ||
stringifyQueryParams = function (parameters) { | ||
return parameters ? parameters.map(function (param) { | ||
var key = param.key; | ||
var 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; | ||
}; | ||
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: function(c) { | ||
@@ -25,11 +140,24 @@ var hex = c.toString(16).toUpperCase(); | ||
/** | ||
* Checks if character at given index in the buffer is already percent encoded or not. | ||
* | ||
* @param {Buffer} buffer | ||
* @param {Number} i | ||
* @returns {Boolean} | ||
*/ | ||
isPreEncoded: function(buffer, i) { | ||
// If it is % check next two bytes for percent encode characters | ||
// looking for pattern %00 - %FF | ||
// If it is % check next two bytes for percent encode characters | ||
// looking for pattern %00 - %FF | ||
return (buffer[i] === 0x25 && | ||
(this.isPreEncodedCharacter(buffer[i + 1]) && | ||
this.isPreEncodedCharacter(buffer[i + 2])) | ||
(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: function(byte) { | ||
@@ -41,2 +169,8 @@ return (byte >= 0x30 && byte <= 0x39) || // 0-9 | ||
/** | ||
* Checks whether given character should be percent encoded or not for fixture. | ||
* | ||
* @param {Number} byte | ||
* @returns {Boolean} | ||
*/ | ||
charactersToPercentEncode: function(byte) { | ||
@@ -49,22 +183,25 @@ return (byte < 0x23 || byte > 0x7E || // Below # and after ~ | ||
byte === 0x2A // * | ||
); | ||
); | ||
}, | ||
/** | ||
* Percent encode a query string according to RFC 3986 | ||
* | ||
* @param value | ||
* @returns {string} | ||
*/ | ||
/** | ||
* 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: function (value) { | ||
if (!value) { return ''; } | ||
if (!value) { return E; } | ||
var buffer = new Buffer(value), | ||
ret = '', | ||
i; | ||
var buffer = Buffer.from(value), | ||
ret = E, | ||
i, | ||
ii; | ||
for (i = 0; i < buffer.length; ++i) { | ||
for (i = 0, ii = buffer.length; i < ii; ++i) { | ||
if (this.charactersToPercentEncode(buffer[i]) && !this.isPreEncoded(buffer, i)) { | ||
ret += this.percentEncode(buffer[i]); | ||
if (encoder.charactersToPercentEncode(buffer[i]) && !encoder.isPreEncoded(buffer, i)) { | ||
ret += encoder.percentEncode(buffer[i]); | ||
} | ||
@@ -77,3 +214,35 @@ else { | ||
return ret; | ||
}, | ||
/** | ||
* Converts URL string into Node's Url object with encoded values | ||
* | ||
* @param {String} url | ||
* @returns {Url} | ||
*/ | ||
toNodeUrl: function (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 = encoder; |
{ | ||
"name": "postman-url-encoder", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": " It encodes the given url string as per RFC 3986.", | ||
@@ -25,4 +25,5 @@ "main": "index.js", | ||
"expect.js": "^0.3.1", | ||
"mocha": "^3.0.0" | ||
"mocha": "^3.0.0", | ||
"postman-collection": "^3.4.6" | ||
} | ||
} |
var expect = require('expect.js'), | ||
urlEncoder = require('./index.js'); | ||
urlEncoder = require('./index.js'), | ||
sdk = require('postman-collection'); | ||
describe('Url Encoding', function () { | ||
describe('Url Encoding fix of node\'s bug', function () { | ||
describe('Encodes' , function() { | ||
it('%', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?charwithPercent=%foo'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?charwithPercent=%25foo'); | ||
}); | ||
describe('Encode' , function() { | ||
it('%', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?charwithPercent=%foo'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?charwithPercent=%25foo'); | ||
}); | ||
it('( and )', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=foo(a)'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=foo%28a%29'); | ||
}); | ||
it('( and )', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=foo(a)'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=foo%28a%29'); | ||
}); | ||
it('Space', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=foo bar'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=foo%20bar'); | ||
}); | ||
it('Space', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=foo bar'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=foo%20bar'); | ||
}); | ||
it('multibyte character "𝌆"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?multibyte=𝌆'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?multibyte=%F0%9D%8C%86'); | ||
}); | ||
it('multibyte character "𝌆"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?multibyte=𝌆'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?multibyte=%F0%9D%8C%86'); | ||
}); | ||
it('Russian charcters "обязательный"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=обязательный'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=%D0%BE%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9'); | ||
}); | ||
it('Russian charcters "обязательный"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=обязательный'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=%D0%BE%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9'); | ||
}); | ||
it('Chinese charcters "你好"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=你好'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=%E4%BD%A0%E5%A5%BD'); | ||
}); | ||
it('Chinese charcters "你好"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=你好'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=%E4%BD%A0%E5%A5%BD'); | ||
}); | ||
it('Japanese charcters "ハローポストマン"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=ハローポストマン'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=%E3%83%8F%E3%83%AD%E3%83%BC%E3%83%9D%E3%82%B9%E3%83%88%E3%83%9E%E3%83%B3'); | ||
}); | ||
it('Japanese charcters "ハローポストマン"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=ハローポストマン'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=%E3%83%8F%E3%83%AD%E3%83%BC%E3%83%9D%E3%82%B9%E3%83%88%E3%83%9E%E3%83%B3'); | ||
}); | ||
it('Partial Russian charcters "Hello Почтальон"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=Hello Почтальон'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD'); | ||
it('Partial Russian charcters "Hello Почтальон"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=Hello Почтальон'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD'); | ||
}); | ||
}); | ||
}) | ||
describe('Do not encode' , function() { | ||
describe('Do not encode' , function() { | ||
it('/, &, =, :, ?, +', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=b&c=d&e=f+g'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=b&c=d&e=f+g'); | ||
}); | ||
it('/, &, =, :, ?, +', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=b&c=d&e=f+g'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=b&c=d&e=f+g'); | ||
}); | ||
it('[ and ]', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a[0]=foo&a[1]=bar'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a[0]=foo&a[1]=bar'); | ||
it('[ and ]', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a[0]=foo&a[1]=bar'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a[0]=foo&a[1]=bar'); | ||
}); | ||
it('pre encoded text( must avoid double encoding) - "email=foo%2Bbar%40domain.com"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?email=foo%2Bbar%40domain.com'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?email=foo%2Bbar%40domain.com'); | ||
}); | ||
it('pre-encoded multibyte character - "multibyte=%F0%9D%8C%86"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?multibyte=%F0%9D%8C%86'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?multibyte=%F0%9D%8C%86'); | ||
}); | ||
it('pre-encoded russian text - "a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD'); | ||
}); | ||
}); | ||
it('pre encoded text( must avoid double encoding) - "email=foo%2Bbar%40domain.com"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?email=foo%2Bbar%40domain.com'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?email=foo%2Bbar%40domain.com'); | ||
}); | ||
describe('toNodeUrl()', function () { | ||
it('should convert postman URL to string properly', function () { | ||
var url = new sdk.Url({ | ||
auth: '', | ||
protocol: 'http', | ||
port: '3000', | ||
path: '/foo/bar', | ||
hash: 'postman', | ||
host: 'www.getpostman.com', | ||
query: { | ||
foo1: 'bar1', | ||
foo2: 'bar2' | ||
}, | ||
}), | ||
expectedResult = { | ||
protocol: 'http:', | ||
slashes: true, | ||
auth: null, | ||
host: 'www.getpostman.com:3000', | ||
port: '3000', | ||
hostname: 'www.getpostman.com', | ||
hash: '#postman', | ||
search: '?foo1=bar1&foo2=bar2', | ||
query: 'foo1=bar1&foo2=bar2', | ||
pathname: '/foo/bar', | ||
path: '/foo/bar?foo1=bar1&foo2=bar2', | ||
href: 'http://www.getpostman.com:3000/foo/bar?foo1=bar1&foo2=bar2#postman' | ||
}, | ||
nodeUrl = urlEncoder.toNodeUrl(url.toString()); | ||
expect(nodeUrl).to.eql(expectedResult); | ||
}); | ||
it('pre-encoded multibyte character - "multibyte=%F0%9D%8C%86"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?multibyte=%F0%9D%8C%86'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?multibyte=%F0%9D%8C%86'); | ||
it('should encode properly while converting to node URL', function () { | ||
var url = new sdk.Url({ | ||
auth: '', | ||
protocol: 'http', | ||
port: '3000', | ||
path: '/foo/bar', | ||
hash: 'postman', | ||
host: 'www.郵便配達員.com', | ||
query: { | ||
foo1: '差', | ||
foo2: 'bar2' | ||
} | ||
}), | ||
expectedResult = { | ||
protocol: 'http:', | ||
slashes: true, | ||
auth: null, | ||
host: 'www.xn--wtqy8jqx5dmsazn.com:3000', | ||
port: '3000', | ||
hostname: 'www.xn--wtqy8jqx5dmsazn.com', | ||
hash: '#postman', | ||
search: '?foo1=%E5%B7%AE&foo2=bar2', | ||
query: 'foo1=%E5%B7%AE&foo2=bar2', | ||
pathname: '/foo/bar', | ||
path: '/foo/bar?foo1=%E5%B7%AE&foo2=bar2', | ||
href: 'http://www.xn--wtqy8jqx5dmsazn.com:3000/foo/bar?foo1=%E5%B7%AE&foo2=bar2#postman' | ||
}, | ||
nodeUrl = urlEncoder.toNodeUrl(url.toString()); | ||
expect(nodeUrl).to.eql(expectedResult); | ||
}); | ||
it('pre-encoded russian text - "a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD"', function () { | ||
var encodedUrl = urlEncoder.encode('http://foo.bar.com?a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD'); | ||
expect(encodedUrl).to.equal('http://foo.bar.com?a=Hello%20%D0%9F%D0%BE%D1%87%D1%82%D0%B0%D0%BB%D1%8C%D0%BE%D0%BD'); | ||
}); | ||
}) | ||
}); |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
20391
328
3
6
2