Skip to content

Commit

Permalink
feat: Throw errors when base URLs are specified incorrectly
Browse files Browse the repository at this point in the history
- Switch to the new URL API which throws errors for most invalid inputs
- Throw errors for URLs with unrecognized schemes
- Add tests for cases that previously had been handled incorrectly

Closes #1061
Supersedes #1065
  • Loading branch information
paulmelnikow committed Aug 22, 2019
1 parent 949d264 commit ea75bca
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 12 deletions.
2 changes: 1 addition & 1 deletion lib/interceptor.js
Expand Up @@ -376,7 +376,7 @@ module.exports = class Interceptor {
}

matchHostName(options) {
return options.hostname === this.scope.urlParts.hostname
return options.hostname === this.scope.parsedUrl.hostname
}

matchQuery(options) {
Expand Down
29 changes: 18 additions & 11 deletions lib/scope.js
Expand Up @@ -13,6 +13,7 @@ const { EventEmitter } = require('events')
const globalEmitter = require('./global_emitter')
const util = require('util')
const Interceptor = require('./interceptor')
const { URL } = url

let fs

Expand Down Expand Up @@ -48,21 +49,27 @@ class Scope extends EventEmitter {
this.matchHeaders = []
this.logger = debug
this.scopeOptions = options || {}
this.urlParts = {}
this._persist = false
this.contentLen = false
this.date = null
this.basePath = basePath
this.basePathname = ''
this.port = null
this._defaultReplyHeaders = []

if (!(basePath instanceof RegExp)) {
this.urlParts = url.parse(basePath)
this.port =
this.urlParts.port || (this.urlParts.protocol === 'http:' ? 80 : 443)
this.basePathname = this.urlParts.pathname.replace(/\/$/, '')
this.basePath = `${this.urlParts.protocol}//${this.urlParts.hostname}:${this.port}`
if (basePath instanceof RegExp) {
this.basePath = basePath
this.basePathname = ''
this.port = null
this.parsedUrl = {}
} else {
this.parsedUrl = new URL(basePath)
const { protocol, hostname, port, pathname } = this.parsedUrl
if (protocol !== 'http:' && protocol !== 'https:') {
throw new TypeError(
`Protocol '${protocol}' not recognized. This commonly occurs when a hostname and port are included without a protocol, producing a URL that is valid but confusing, and probably not what you want.`
)
}
this.port = port || (protocol === 'http:' ? 80 : 443)
this.basePathname = pathname.replace(/\/$/, '')
this.basePath = `${protocol}//${hostname}:${this.port}`
}
}

Expand All @@ -76,7 +83,7 @@ class Scope extends EventEmitter {
interceptor,
this,
this.scopeOptions,
this.urlParts.hostname
this.parsedUrl.hostname
)
}

Expand Down
22 changes: 22 additions & 0 deletions tests/test_intercept.js
Expand Up @@ -1452,3 +1452,25 @@ test('works when headers are removed on the socket event', t => {
t.end()
})
})

// https://github.com/nock/nock/issues/1061
test('invalid URLs throw', t => {
;['localhost:1234', 'localhost:1234/url'].forEach(invalidUrl => {
t.throws(() => nock('localhost:1234/url'), {
message: `Protocol 'localhost:' not recognized. This commonly occurs when a hostname and port are included without a protocol, producing a URL that is valid but confusing, and probably not what you want.`,
})
})
;[
'localhost',
'127.0.0.1',
'127.0.0.1:1234',
'127.0.0.1:1234/url',
'foo.com/api',
].forEach(invalidUrl => {
t.throws(() => nock(invalidUrl), {
input: invalidUrl,
name: 'TypeError [ERR_INVALID_URL]',
})
})
t.end()
})

0 comments on commit ea75bca

Please sign in to comment.