Skip to content

Commit

Permalink
Introduce 'lenient' mode for hostname validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
remusao committed Mar 16, 2018
1 parent 42e5bd3 commit a6a3f1b
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 5 deletions.
18 changes: 16 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,22 @@ var ALL = 5;
function factory(options) {
var rules = options.rules || allRules || {};
var validHosts = options.validHosts || [];
var lenientHostnameValidation = options.lenientHostnameValidation === true;
var _extractHostname = options.extractHostname || extractHostname;

var isValidHostname = isValid;
if (lenientHostnameValidation) {
// If 'lenient' mode is enabled, then underscores are allowed to appear in
// hostnames. By default, only alphanumeric characters as well as '-' is
// allowed.
isValidHostname = function (hostname) {
return isValid(hostname, function (code) {
return code === 45 || code === 95;
// ^ - (dash) ^ _ (underscore)
});
};
}

/**
* Process a given url and extract all information. This is a higher level API
* around private functions of `tld.js`. It allows to remove duplication (only
Expand Down Expand Up @@ -73,7 +87,7 @@ function factory(options) {
}

// Check if `hostname` is valid
result.isValid = isValid(result.hostname);
result.isValid = isValidHostname(result.hostname);
if (result.isValid === false) return result;

// Check if tld exists
Expand All @@ -99,7 +113,7 @@ function factory(options) {

return {
extractHostname: _extractHostname,
isValid: isValid,
isValid: isValidHostname,
parse: parse,
tldExists: function (url) {
return parse(url, TLD_EXISTS).tldExists;
Expand Down
11 changes: 8 additions & 3 deletions lib/is-valid.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ function isAlpha(code) {
* @param {string} hostname
* @return {boolean}
*/
module.exports = function isValid(hostname) {
module.exports = function isValid(hostname, _extraValidCode) {
var extraValidCode = function (code) { return code === 45; };
if (_extraValidCode !== undefined) {
extraValidCode = _extraValidCode;
}

if (typeof hostname !== 'string') {
return false;
}
Expand Down Expand Up @@ -72,13 +77,13 @@ module.exports = function isValid(hostname) {
// Check that previous character was not already a '.'
lastCharCode === 46 ||
// Check that the previous label does not end with a '-'
lastCharCode === 45
extraValidCode(lastCharCode)
) {
return false;
}

lastDotIndex = i;
} else if (!(isAlpha(code) || isDigit(code) || code === 45)) {
} else if (!(isAlpha(code) || isDigit(code) || extraValidCode(code))) {
// Check if there is a forbidden character in the label: [^a-zA-Z0-9-]
return false;
}
Expand Down
8 changes: 8 additions & 0 deletions test/tld.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ describe('tld.js', function () {
expect(tld.isValid('example.' + repeat('a', 63) + '.')).to.be(true);
expect(tld.isValid('example.' + repeat('a', 63))).to.be(true);

// Rejects domains with '_'
expect(tld.isValid('foo.bar_baz.com')).to.be(false);

//@see https://github.com/oncletom/tld.js/issues/95
expect(tld.isValid('miam.miam.google.com.')).to.be(true);

Expand All @@ -92,6 +95,11 @@ describe('tld.js', function () {
expect(tld.isValid('.google.com')).to.be(false);
expect(tld.isValid('.com')).to.be(false);
});

it('should accept extra code points in domain with lenien mode', function () {
var customTld = tld.fromUserSettings({ lenientHostnameValidation: true });
expect(customTld.isValid('foo.bar_baz.com')).to.be(true);
});
});

describe('isIp method', function () {
Expand Down

0 comments on commit a6a3f1b

Please sign in to comment.