Skip to content

Commit bff0d95

Browse files
ErisDSacburdine
authored andcommitted
Add new URL utility
1 parent af5b8f5 commit bff0d95

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

lib/utils/url.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
3+
const {isURL} = require('validator');
4+
const endsWithGhost = /\/ghost\/?$/i;
5+
6+
const validate = function validateURL(url) {
7+
const isValidURL = isURL(url, {require_protocol: true});
8+
if (!isValidURL) {
9+
return 'Invalid URL. Your URL should include a protocol, E.g. http://my-ghost-blog.com';
10+
}
11+
12+
return (!endsWithGhost.test(url)) || 'Ghost doesn\'t support running in a path that ends with `ghost`';
13+
};
14+
15+
const isCustomDomain = function isCustomDomain(input) {
16+
// If this is localhost or an IP, it's not a custom domain
17+
return !(/localhost/.test(input) || /((\d){1,3}\.){3}(\d){1,3}/.test(input));
18+
};
19+
20+
const ensureProtocol = function ensureProtocol(input) {
21+
let output = input.toLowerCase().trim();
22+
let proto = '';
23+
24+
if (!/^http/.test(output)) {
25+
// Custom domains should always be HTTPS, localhost/IP should be HTTP
26+
proto = isCustomDomain(output) ? 'https:' : 'http:';
27+
28+
// If this doesn't start with 2 slashes, add them
29+
if (!/^\/\//.test(output)) {
30+
proto = proto + '//';
31+
}
32+
}
33+
34+
return proto + output;
35+
};
36+
37+
module.exports = {
38+
validate,
39+
isCustomDomain,
40+
ensureProtocol
41+
};

test/unit/utils/url.js

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
'use strict';
2+
3+
const {expect} = require('chai');
4+
5+
const url = require('../../../lib/utils/url');
6+
7+
describe('Unit: Utils > URL', function () {
8+
describe('> Validate', function () {
9+
it('non-URLs fail', function () {
10+
expect(url.validate('totally a url')).to.match(/Invalid URL/);
11+
expect(url.validate('notaurl')).to.match(/Invalid URL/);
12+
});
13+
14+
it('protocol-free URLs fail', function () {
15+
expect(url.validate('myghost.blog')).to.match(/include a protocol/);
16+
});
17+
18+
it('trailing `ghost` subdir fails', function () {
19+
expect(url.validate('https://myghost.blog/myghost/')).to.be.true;
20+
expect(url.validate('https://myghost.blog/ghosted/')).to.be.true;
21+
expect(url.validate('https://myghost.blog/ghost')).to.match(/path that ends with `ghost`/);
22+
expect(url.validate('https://myghost.blog/ghost/')).to.match(/path that ends with `ghost`/);
23+
});
24+
25+
it('everything else works', function () {
26+
expect(url.validate('http://localhost:2368/')).to.be.true;
27+
expect(url.validate('http://localhost:2368/testing')).to.be.true;
28+
expect(url.validate('https://myghost.blog/')).to.be.true;
29+
expect(url.validate('https://ghost.org/blog')).to.be.true;
30+
expect(url.validate('https://blog.ghost.org/')).to.be.true;
31+
});
32+
});
33+
34+
describe('> isCustomDomain', function () {
35+
it('localhost fails', function () {
36+
expect(url.isCustomDomain('localhost')).to.be.false;
37+
});
38+
39+
it('localhost with port fails', function () {
40+
expect(url.isCustomDomain('localhost:2368')).to.be.false;
41+
});
42+
43+
it('localhost with protocol fails', function () {
44+
expect(url.isCustomDomain('http://localhost')).to.be.false;
45+
});
46+
47+
it('IP address fails', function () {
48+
expect(url.isCustomDomain('168.123.45.1')).to.be.false;
49+
});
50+
51+
it('IP with port fails', function () {
52+
expect(url.isCustomDomain('168.123.45.1:2368')).to.be.false;
53+
});
54+
55+
it('IP with protocol fails', function () {
56+
expect(url.isCustomDomain('http://168.123.45.1')).to.be.false;
57+
});
58+
59+
it('domain with one TLD passes', function () {
60+
expect(url.isCustomDomain('example.com')).to.be.true;
61+
});
62+
63+
it('domain with two TLDs passes', function () {
64+
expect(url.isCustomDomain('example.co.uk')).to.be.true;
65+
});
66+
67+
it('domain with protocol passes', function () {
68+
expect(url.isCustomDomain('http://example.com')).to.be.true;
69+
});
70+
});
71+
72+
describe('> ensureProtocol', function () {
73+
it('adds http to localhost', function () {
74+
expect(url.ensureProtocol('localhost')).to.eql('http://localhost');
75+
});
76+
77+
it('adds http to localhost with port', function () {
78+
expect(url.ensureProtocol('localhost:2368')).to.eql('http://localhost:2368');
79+
});
80+
81+
it('adds http to localhost with slasshes', function () {
82+
expect(url.ensureProtocol('//localhost')).to.eql('http://localhost');
83+
});
84+
85+
it('does not add http to localhost with protocol', function () {
86+
expect(url.ensureProtocol('http://localhost')).to.eql('http://localhost');
87+
});
88+
89+
it('adds http to IP address', function () {
90+
expect(url.ensureProtocol('168.123.45.1')).to.eql('http://168.123.45.1');
91+
});
92+
93+
it('adds http to IP with port', function () {
94+
expect(url.ensureProtocol('168.123.45.1:2368')).to.eql('http://168.123.45.1:2368');
95+
});
96+
97+
it('adds http to IP address with slasshes', function () {
98+
expect(url.ensureProtocol('//168.123.45.1')).to.eql('http://168.123.45.1');
99+
});
100+
101+
it('does not add http to IP with protocol', function () {
102+
expect(url.ensureProtocol('http://168.123.45.1')).to.eql('http://168.123.45.1');
103+
});
104+
105+
it('adds https to domain with one TLD', function () {
106+
expect(url.ensureProtocol('example.com')).to.eql('https://example.com');
107+
});
108+
109+
it('adds https to domain with two TLDs', function () {
110+
expect(url.ensureProtocol('example.co.uk')).to.eql('https://example.co.uk');
111+
});
112+
113+
it('adds https to domain with slashes', function () {
114+
expect(url.ensureProtocol('//example.com')).to.eql('https://example.com');
115+
});
116+
117+
it('does not add https to domain with protocol', function () {
118+
expect(url.ensureProtocol('http://example.com')).to.eql('http://example.com');
119+
});
120+
});
121+
});

0 commit comments

Comments
 (0)