From a59b2a1a937025abe29d3105ff9095ec1279f30e Mon Sep 17 00:00:00 2001 From: "Matt R. Wilson" Date: Thu, 8 Aug 2019 10:46:39 -0600 Subject: [PATCH] bug(overrider): unmocked HTTPS request with partial interceptor match Fixes: #1422 The `allowUnmocked` option is processed in two places. Once in the intercept when there are no interceptors that come close to matching the request. And again in the overrider when there are interceptors that partially match, eg just path, but don't completely match. This fixes and explicitly tests the later case in the overrider by making an HTTPS request for a path that has an interceptor but fails to match the query constraint. --- lib/request_overrider.js | 13 +++++++++-- tests/test_allow_unmocked_https.js | 35 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/lib/request_overrider.js b/lib/request_overrider.js index 5aaa3dc72..b6ad59151 100644 --- a/lib/request_overrider.js +++ b/lib/request_overrider.js @@ -2,7 +2,12 @@ const debug = require('debug')('nock.request_overrider') const { EventEmitter } = require('events') -const { IncomingMessage, ClientRequest } = require('http') +const { + IncomingMessage, + ClientRequest, + request: originalHttpRequest, +} = require('http') +const { request: originalHttpsRequest } = require('https') const _ = require('lodash') const propagate = require('propagate') const timers = require('timers') @@ -253,7 +258,11 @@ function RequestOverrider(req, options, interceptors, remove) { ) if (allowUnmocked && req instanceof ClientRequest) { - const newReq = new ClientRequest(options) + const newReq = + options.proto === 'https' + ? originalHttpsRequest(options) + : originalHttpRequest(options) + propagate(newReq, req) // We send the raw buffer as we received it, not as we interpreted it. newReq.end(requestBodyBuffer) diff --git a/tests/test_allow_unmocked_https.js b/tests/test_allow_unmocked_https.js index 494cd915d..0a6c879e6 100644 --- a/tests/test_allow_unmocked_https.js +++ b/tests/test_allow_unmocked_https.js @@ -109,3 +109,38 @@ test('allow unmocked option works with https', t => { .end() }) }) + +test('allow unmocked option works with https for a partial match', t => { + // The `allowUnmocked` option is processed in two places. Once in the intercept when there + // are no interceptors that come close to matching the request. And again in the overrider when + // there are interceptors that partially match, eg just path, but don't completely match. + // This explicitly tests the later case in the overrider by making an HTTPS request for a path + // that has an interceptor but fails to match the query constraint. + + function middleware(request, response) { + response.writeHead(201) + response.write('foo') + response.end() + } + + ssl.startServer(middleware, function(error, server) { + t.error(error) + + const { port } = server.address() + const origin = `https://localhost:${port}` + + nock(origin, { allowUnmocked: true }) + .get('/foo') + .query({ foo: 'bar' }) + .reply(418) + + // no query so wont match the interceptor + got(`${origin}/foo`, { rejectUnauthorized: false }).then( + ({ body, statusCode }) => { + t.is(statusCode, 201) + t.is(body, 'foo') + server.close(t.end) + } + ) + }) +})