0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-01 02:41:39 -05:00

Prepared config-url-helpers for their intended use

- added getSubdir, getSiteUrl and getAdminUrl methods from url-utils
- refactored them so they are designed to be bound by nconf
- exposed a bindAll method
- moved over the tests and refactor from a class instance to nconf bindings
This commit is contained in:
Hannah Wolfe 2021-06-17 11:41:06 +01:00
parent 320e689ad4
commit eb829a050b
7 changed files with 255 additions and 12 deletions

View file

@ -1 +1,7 @@
module.exports = require('./lib/config-url-helpers');
const configUrlHelpers = require('./lib/config-url-helpers');
module.exports.bindAll = (nconf) => {
Object.keys(configUrlHelpers).forEach((helper) => {
nconf[helper] = configUrlHelpers[helper].bind(nconf);
});
};

View file

@ -0,0 +1,75 @@
const deduplicateSubdirectory = require('./utils/deduplicate-subdirectory');
/**
* Returns a subdirectory URL, if defined so in the config.
* @return {string} URL a subdirectory if configured.
*/
function getSubdir() {
// Parse local path location
let {pathname} = new URL(this.get('url'));
let subdir;
// Remove trailing slash
if (pathname !== '/') {
pathname = pathname.replace(/\/$/, '');
}
subdir = pathname === '/' ? '' : pathname;
return subdir;
}
/**
* Returns the base URL of the site as set in the config.
*
* Secure:
* If the request is secure, we want to force returning the site url as https.
* Imagine Ghost runs with http, but nginx allows SSL connections.
*
* @param {boolean} secure
* @return {string} returns the url as defined in config, but always with a trailing `/`
*/
function getSiteUrl(secure = false) {
let siteUrl = this.get('url');
if (secure) {
siteUrl = siteUrl.replace('http://', 'https://');
}
if (!siteUrl.match(/\/$/)) {
siteUrl += '/';
}
return siteUrl;
}
/**
*
* @returns {string}
*/
function getAdminUrl() {
let adminUrl = this.get('admin:url');
const subdir = this.getSubdir();
if (!adminUrl) {
return;
}
if (!adminUrl.match(/\/$/)) {
adminUrl += '/';
}
adminUrl = `${adminUrl}${subdir}`;
if (!adminUrl.match(/\/$/)) {
adminUrl += '/';
}
adminUrl = deduplicateSubdirectory(adminUrl, this.getSiteUrl());
return adminUrl;
}
module.exports = {
getSubdir,
getSiteUrl,
getAdminUrl
};

View file

@ -13,6 +13,9 @@ const deduplicateSubdirectory = function deduplicateSubdirectory(url, rootUrl) {
rootUrl = `${rootUrl}/`;
}
// Cleanup any extraneous slashes in url for consistent behaviour
url = url.replace(/(^|[^:])\/\/+/g, '$1/');
const parsedRoot = new URL(rootUrl);
// do nothing if rootUrl does not have a subdirectory

View file

@ -7,7 +7,8 @@
"main": "index.js",
"scripts": {
"dev": "echo \"Implement me!\"",
"test": "NODE_ENV=testing mocha './test/**/*.test.js'",
"test": "NODE_ENV=testing c8 --check-coverage mocha './test/**/*.test.js'",
"coverage": "c8 report -r html",
"lint": "eslint . --ext .js --cache",
"posttest": "yarn lint"
},
@ -19,6 +20,7 @@
"access": "public"
},
"devDependencies": {
"c8": "^7.7.3",
"mocha": "9.0.0",
"should": "13.2.3",
"sinon": "11.1.1"

View file

@ -0,0 +1,121 @@
// Switch these lines once there are useful utils
// const testUtils = require('./utils');
require('./utils');
const sinon = require('sinon');
const configUrlHelpers = require('../');
let nconf;
const fakeConfig = {
url: '',
adminUrl: null
};
describe('Config URL Helpers', function () {
before(function () {
const configFaker = (arg) => {
if (arg === 'url') {
return fakeConfig.url;
} else if (arg === 'admin:url') {
return fakeConfig.adminUrl;
}
};
nconf = {
get: sinon.stub().callsFake(configFaker)
};
configUrlHelpers.bindAll(nconf);
});
describe('getSiteUrl', function () {
it('returns config url', function () {
fakeConfig.url = 'http://example.com/';
nconf.getSiteUrl().should.eql('http://example.com/');
});
it('adds trailing slash', function () {
fakeConfig.url = 'http://example.com';
nconf.getSiteUrl().should.eql('http://example.com/');
});
it('returns https if secure=true', function () {
fakeConfig.url = 'http://example.com/';
nconf.getSiteUrl(true).should.eql('https://example.com/');
});
});
describe('getAdminUrl', function () {
it('returns undefinied if no admin URL is set', function () {
should.not.exist(nconf.getAdminUrl());
});
it('returns config url', function () {
fakeConfig.adminUrl = 'http://admin.example.com/';
nconf.getAdminUrl().should.eql('http://admin.example.com/');
});
it('adds trailing slash', function () {
fakeConfig.adminUrl = 'http://admin.example.com';
nconf.getAdminUrl().should.eql('http://admin.example.com/');
});
it('returns with subdirectory correctly if not provided', function () {
fakeConfig.url = 'http://example.com/blog/';
fakeConfig.adminUrl = 'http://admin.example.com';
nconf.getAdminUrl().should.eql('http://admin.example.com/blog/');
});
it('returns with subdirectory correctly if provided with slash', function () {
fakeConfig.url = 'http://example.com/blog/';
fakeConfig.adminUrl = 'http://admin.example.com/blog/';
nconf.getAdminUrl().should.eql('http://admin.example.com/blog/');
});
it('returns with subdirectory correctly if provided without slash', function () {
fakeConfig.url = 'http://example.com/blog/';
fakeConfig.adminUrl = 'http://admin.example.com/blog';
nconf.getAdminUrl().should.eql('http://admin.example.com/blog/');
});
});
describe('getSubdir', function () {
it('url has no subdir', function () {
fakeConfig.url = 'http://my-ghost-blog.com/';
nconf.getSubdir().should.eql('');
});
it('url has subdir', function () {
fakeConfig.url = 'http://my-ghost-blog.com/blog';
nconf.getSubdir().should.eql('/blog');
fakeConfig.url = 'http://my-ghost-blog.com/blog/';
nconf.getSubdir().should.eql('/blog');
fakeConfig.url = 'http://my-ghost-blog.com/my/blog';
nconf.getSubdir().should.eql('/my/blog');
fakeConfig.url = 'http://my-ghost-blog.com/my/blog/';
nconf.getSubdir().should.eql('/my/blog');
});
it('should not return a slash for subdir', function () {
fakeConfig.url = 'http://my-ghost-blog.com';
nconf.getSubdir().should.eql('');
fakeConfig.url = 'http://my-ghost-blog.com/';
nconf.getSubdir().should.eql('');
});
});
});

View file

@ -1,10 +0,0 @@
// Switch these lines once there are useful utils
// const testUtils = require('./utils');
require('./utils');
describe('Hello world', function () {
it('Runs a test', function () {
// TODO: Write me!
'hello'.should.eql('hello');
});
});

View file

@ -136,4 +136,50 @@ describe('utils: deduplicateSubdirectory()', function () {
.should.equal('/blog/', 'with root trailing-slash');
});
});
describe('with multiple slashes', function () {
it('handles double slash between root and subdir', function () {
deduplicateSubdirectory('http://admin.example.com//blog/blog/', 'http://example.com/blog')
.should.equal('http://admin.example.com/blog/', 'without root trailing-slash');
deduplicateSubdirectory('http://admin.example.com//blog/blog/', 'http://example.com/blog/')
.should.equal('http://admin.example.com/blog/', 'with root trailing-slash');
deduplicateSubdirectory('http://admin.example.com//blog/', 'http://example.com/blog')
.should.equal('http://admin.example.com/blog/', 'without root trailing-slash');
deduplicateSubdirectory('http://admin.example.com//blog/', 'http://example.com/blog/')
.should.equal('http://admin.example.com/blog/', 'with root trailing-slash');
});
it('handles double slash between duplicates', function () {
deduplicateSubdirectory('http://admin.example.com/blog//blog/', 'http://example.com/blog')
.should.equal('http://admin.example.com/blog/', 'without root trailing-slash');
deduplicateSubdirectory('http://admin.example.com/blog//blog/', 'http://example.com/blog/')
.should.equal('http://admin.example.com/blog/', 'with root trailing-slash');
});
it('handles double slash after subdirs', function () {
deduplicateSubdirectory('http://admin.example.com/blog/blog//', 'http://example.com/blog')
.should.equal('http://admin.example.com/blog/', 'without root trailing-slash');
deduplicateSubdirectory('http://admin.example.com/blog/blog//', 'http://example.com/blog/')
.should.equal('http://admin.example.com/blog/', 'with root trailing-slash');
deduplicateSubdirectory('http://admin.example.com/blog//', 'http://example.com/blog')
.should.equal('http://admin.example.com/blog/', 'without root trailing-slash');
deduplicateSubdirectory('http://admin.example.com/blog//', 'http://example.com/blog/')
.should.equal('http://admin.example.com/blog/', 'with root trailing-slash');
});
it('handles double slashes everywhere', function () {
deduplicateSubdirectory('http://admin.example.com//blog//blog//', 'http://example.com/blog')
.should.equal('http://admin.example.com/blog/', 'without root trailing-slash');
deduplicateSubdirectory('http://admin.example.com//blog//blog//', 'http://example.com/blog/')
.should.equal('http://admin.example.com/blog/', 'with root trailing-slash');
});
});
});