Skip to content

Commit

Permalink
improving URL syntax compliance.
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaly-t committed Jul 13, 2017
1 parent 3340e76 commit 5523127
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 22 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "connection-string",
"version": "0.1.1",
"version": "0.1.2",
"description": "URL Connection String Parser.",
"main": "src/index.js",
"typings": "src/index.d.ts",
Expand Down
10 changes: 5 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@
var result = {};

// extract the protocol:
var m = cs.match(/^[\w-%]*:\/+/);
var m = cs.match(/^[\w-_.+!*'()$%]*:\/\//);
if (m) {
result.protocol = decodeURI(m[0].replace(/:\/*/, ''));
result.protocol = decodeURI(m[0].replace(/:\/\//, ''));
cs = cs.substr(m[0].length);
if (!result.protocol) {
throw new TypeError('Invalid \'protocol\' specification.');
}
}

// extract user + password:
m = cs.match(/^([\w-%]*):?([\w-%]*)@/);
m = cs.match(/^([\w-_.+!*'()$%]*):?([\w-_.+!*'()$%]*)@/);
if (m) {
if (m[1]) {
result.user = decodeURI(m[1]);
Expand Down Expand Up @@ -66,7 +66,7 @@
}

// extract segments:
m = cs.match(/\/([^/?]+)/g);
m = cs.match(/\/([\w-_.+!*'()$%]+)/g);
if (m) {
result.segments = m.map(function (s) {
return decodeURI(s.substr(1));
Expand All @@ -77,7 +77,7 @@
idx = cs.indexOf('?');
if (idx !== -1) {
cs = cs.substr(idx + 1);
m = cs.match(/([^=&?]+)=([^&=?]+)/g);
m = cs.match(/([\w-_.+!*'()$%]+)=([\w-_.+!*'()$%]+)/g);
if (m) {
result.params = {};
m.forEach(function (s) {
Expand Down
54 changes: 38 additions & 16 deletions test/mainSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,46 +30,48 @@ describe('protocol', function () {
it('must recognize standard format', function () {
expect(parse('abc://')).toEqual({protocol: 'abc'});
});
it('must recognize short format', function () {
expect(parse('abc:/')).toEqual({protocol: 'abc'});
});
it('must recognize redundant format', function () {
expect(parse('abc:///')).toEqual({protocol: 'abc'});
expect(parse('abc://///')).toEqual({protocol: 'abc'});
it('must ignore incomplete format', function () {
expect(parse('abc:/')).toEqual({host: 'abc', hostname: 'abc'});
});
it('must throw on invalid format', function () {
var error = new TypeError('Invalid \'protocol\' specification.');
expect(function () {
parse('://');
}).toThrow(error);
expect(function () {
parse(':/');
}).toThrow(error);
expect(function () {
parse('://///');
}).toThrow(error);
});
it('must decode special characters', function () {
it('must decode URL-encoded characters', function () {
expect(parse('a%20b://')).toEqual({protocol: 'a b'});
});
it('must support special symbols', function () {
expect(parse('$-_.+!*\'()://')).toEqual({protocol: '$-_.+!*\'()'});
});
});

describe('user', function () {
it('must allow only the user', function () {
expect(parse('name@')).toEqual({user: 'name'});
});
it('must decode special characters', function () {
it('must decode URL-encoded characters', function () {
expect(parse('first%20name@')).toEqual({user: 'first name'});
});
it('must support special symbols', function () {
expect(parse('$-_.+!*\'()@')).toEqual({user: '$-_.+!*\'()'});
});
});

describe('password', function () {
it('must allow only the password', function () {
expect(parse(':pass@')).toEqual({password: 'pass'});
});
it('must decode special characters', function () {
it('must decode URL-encoded characters', function () {
expect(parse(':pass%20123@')).toEqual({password: 'pass 123'});
});
it('must support special symbols', function () {
expect(parse(':$-_.+!*\'()@')).toEqual({password: '$-_.+!*\'()'});
});
});

describe('user+password', function () {
Expand Down Expand Up @@ -141,9 +143,16 @@ describe('segments', function () {
it('must enumerate all segments', function () {
expect(parse('/one/two')).toEqual({segments: ['one', 'two']});
});
it('must decode special characters', function () {
it('must recognize after protocol', function () {
expect(parse('abc:///one')).toEqual({protocol: 'abc', segments: ['one']});
expect(parse('abc:////one')).toEqual({protocol: 'abc', segments: ['one']});
});
it('must decode URL-encoded characters', function () {
expect(parse('/one%20/%20two')).toEqual({segments: ['one ', ' two']});
});
it('must support special symbols', function () {
expect(parse('/$-_.+!*\'()')).toEqual({segments: ['$-_.+!*\'()']});
});
});

describe('params', function () {
Expand All @@ -167,22 +176,29 @@ describe('params', function () {
}
});
});
it('must decode special characters', function () {
it('must decode URL-encoded characters', function () {
expect(parse('?a%20b=test')).toEqual({
params: {
'a b': 'test'
}
});
});
it('must support special symbols', function () {
expect(parse('?$-_.+!*\'()=$-_.+!*\'()')).toEqual({
params: {
'$-_.+!*\'()': '$-_.+!*\'()'
}
});
});
});

describe('complex', function () {
it('protocol + segment', function () {
expect(parse('a://:/seg')).toEqual({
expect(parse('a:///seg')).toEqual({
protocol: 'a',
segments: ['seg']
});
expect(parse('a:/@/seg')).toEqual({
expect(parse('a:////seg')).toEqual({
protocol: 'a',
segments: ['seg']
});
Expand All @@ -194,5 +210,11 @@ describe('complex', function () {
one: '1'
}
});
expect(parse('a:////?one=1')).toEqual({
protocol: 'a',
params: {
one: '1'
}
});
});
});

0 comments on commit 5523127

Please sign in to comment.