Skip to content

Commit 6c14755

Browse files
committed
Exclude default ports 80/443 from base URL
Fix #59.
1 parent 712197e commit 6c14755

File tree

4 files changed

+145
-1
lines changed

4 files changed

+145
-1
lines changed

oauth-1.0a.d.ts

+23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ declare class OAuth {
1717
signature_metho: string;
1818
version: string;
1919

20+
private _urlPattern: RegExp;
21+
2022
constructor(opts?: OAuth.Options);
2123

2224
/**
@@ -93,6 +95,14 @@ declare class OAuth {
9395
*/
9496
mergeObject<T, U>(obj1: T, obj2: U): T & U;
9597

98+
/**
99+
* Parse an URL into its various component.
100+
*
101+
* Does no normalisation but throw if it encounters non-ascii char or if the
102+
* URL does represent a http(s) request.
103+
*/
104+
parseUrl(url: string): OAuth.URL;
105+
96106
/**
97107
* Sort an object properties by keys.
98108
*/
@@ -189,4 +199,17 @@ declare namespace OAuth {
189199
secret: string;
190200
}
191201

202+
/**
203+
* URL components
204+
*/
205+
export interface URL {
206+
auth: string;
207+
hash: string;
208+
hostname: string;
209+
pathname: string;
210+
port: string;
211+
protocol: 'http' | 'https';
212+
search: string;
213+
}
214+
192215
}

oauth-1.0a.js

+42-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,18 @@ OAuth.prototype.getSigningKey = function(token_secret) {
194194
* @return {String}
195195
*/
196196
OAuth.prototype.getBaseUrl = function(url) {
197-
return url.split('?')[0];
197+
var parsed = this.parseUrl(url);
198+
var port = parsed.port;
199+
var protocol = parsed.protocol.toLowerCase();
200+
201+
if (
202+
(port === ':80' && protocol === 'http') ||
203+
(port === ':443' && protocol === 'https')
204+
) {
205+
parsed.port = '';
206+
}
207+
208+
return parsed.protocol + '://' + parsed.auth + parsed.hostname + parsed.port + parsed.pathname;
198209
};
199210

200211
/**
@@ -354,6 +365,36 @@ OAuth.prototype.mergeObject = function(obj1, obj2) {
354365
return merged_obj;
355366
};
356367

368+
OAuth.prototype._urlPattern = /^(https?):\/\/([^:]+:[^@]+@)?([^:/?#]+)(\:\d+)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$/;
369+
370+
/**
371+
* Parse an URL into its various component.
372+
*
373+
* Does no normalisation but throw if it encounters non-ascii char or if the
374+
* URL does represent a http(s) request.
375+
*
376+
* @param {string} url Url to parse
377+
* @returns {object}
378+
*/
379+
OAuth.prototype.parseUrl = function(url) {
380+
var match = this._urlPattern.exec(url);
381+
var components;
382+
383+
if (match == null || match.len < 8) {
384+
throw new Error('Invalid URL: "' + url + '".');
385+
}
386+
387+
return {
388+
protocol: match[1],
389+
auth: match[2] || '',
390+
hostname: match[3],
391+
port: match[4] || '',
392+
pathname: match[5] || '',
393+
search: match[6] || '',
394+
hash: match[7] || ''
395+
};
396+
};
397+
357398
/**
358399
* Sort object by key
359400
* @param {Object} data

test/getBaseUrl.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var expect = require('chai').expect;
2+
var OAuth = require('../oauth-1.0a');
3+
4+
describe('#getBaseUrl', function() {
5+
var oauth = new OAuth({consumer: {}});
6+
7+
beforeEach(function () {
8+
oauth = new OAuth({consumer: {}});
9+
});
10+
11+
it('should return base url', function () {
12+
expect(oauth.getBaseUrl('http://example.com/path/')).to.equal('http://example.com/path/');
13+
expect(oauth.getBaseUrl('http://example.com/path/?foo=bar')).to.equal('http://example.com/path/');
14+
});
15+
16+
it('should exclude default port number', function () {
17+
expect(oauth.getBaseUrl('http://example.com/')).to.equal('http://example.com/');
18+
expect(oauth.getBaseUrl('http://example.com:80/')).to.equal('http://example.com/');
19+
expect(oauth.getBaseUrl('https://example.com/')).to.equal('https://example.com/');
20+
expect(oauth.getBaseUrl('https://example.com:443/')).to.equal('https://example.com/');
21+
});
22+
23+
it('should include non-default port number', function () {
24+
expect(oauth.getBaseUrl('http://example.com:8080/')).to.equal('http://example.com:8080/');
25+
expect(oauth.getBaseUrl('http://example.com:443/')).to.equal('http://example.com:443/');
26+
expect(oauth.getBaseUrl('https://example.com:8080/')).to.equal('https://example.com:8080/');
27+
expect(oauth.getBaseUrl('https://example.com:80/')).to.equal('https://example.com:80/');
28+
});
29+
});

test/parseUrl.js

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
var expect = require('chai').expect;
2+
var OAuth = require('../oauth-1.0a');
3+
4+
describe('OAuth.parseUrl', function() {
5+
var oauth = new OAuth({consumer: {}});
6+
7+
beforeEach(function () {
8+
oauth = new OAuth({consumer: {}});
9+
});
10+
11+
it('should parse protocol', function () {
12+
expect(oauth.parseUrl('http://example.com/').protocol).to.equal('http');
13+
expect(oauth.parseUrl('https://example.com/').protocol).to.equal('https');
14+
});
15+
16+
it('should parse auth component', function () {
17+
expect(oauth.parseUrl('http://example.com/').auth).to.equal('');
18+
expect(oauth.parseUrl('http://foo:[email protected]/').auth).to.equal('foo:bar@');
19+
});
20+
21+
it('should parse hostname component', function () {
22+
expect(oauth.parseUrl('http://example.com/').hostname).to.equal('example.com');
23+
expect(oauth.parseUrl('http://example.com:8080/').hostname).to.equal('example.com');
24+
expect(oauth.parseUrl('http://foo:[email protected]/').hostname).to.equal('example.com');
25+
});
26+
27+
it('should parse port component', function () {
28+
expect(oauth.parseUrl('http://example.com/').port).to.equal('');
29+
expect(oauth.parseUrl('http://example.com:80/').port).to.equal(':80');
30+
expect(oauth.parseUrl('http://foo:[email protected]:80/').port).to.equal(':80');
31+
});
32+
33+
it('should parse pathname component', function () {
34+
expect(oauth.parseUrl('http://example.com').pathname).to.equal('');
35+
expect(oauth.parseUrl('http://example.com/').pathname).to.equal('/');
36+
expect(oauth.parseUrl('http://example.com/foo/bar').pathname).to.equal('/foo/bar');
37+
});
38+
39+
it('should parse search component', function () {
40+
expect(oauth.parseUrl('http://example.com').search).to.equal('');
41+
expect(oauth.parseUrl('http://example.com/?foo').search).to.equal('?foo');
42+
expect(oauth.parseUrl('http://example.com/?foo#bar').search).to.equal('?foo');
43+
expect(oauth.parseUrl('http://example.com/?foo?bar').search).to.equal('?foo?bar');
44+
});
45+
46+
it('should parse hash component', function () {
47+
expect(oauth.parseUrl('http://example.com').hash).to.equal('');
48+
expect(oauth.parseUrl('http://example.com/?foo').hash).to.equal('');
49+
expect(oauth.parseUrl('http://example.com/?foo#bar').hash).to.equal('#bar');
50+
});
51+
});

0 commit comments

Comments
 (0)