|
1 | 1 | 'use strict' |
2 | 2 |
|
3 | | -const debug = require('debug')('nock.common') |
| 3 | +const { common: debug } = require('./debug') |
4 | 4 | const timers = require('timers') |
5 | 5 | const url = require('url') |
6 | 6 | const util = require('util') |
| 7 | +const http = require('http') |
7 | 8 |
|
8 | 9 | /** |
9 | 10 | * Normalizes the request options so that it always has `host` property. |
@@ -50,82 +51,6 @@ function isUtf8Representable(buffer) { |
50 | 51 | return reconstructedBuffer.equals(buffer) |
51 | 52 | } |
52 | 53 |
|
53 | | -// Array where all information about all the overridden requests are held. |
54 | | -let requestOverrides = {} |
55 | | - |
56 | | -/** |
57 | | - * Overrides the current `request` function of `http` and `https` modules with |
58 | | - * our own version which intercepts issues HTTP/HTTPS requests and forwards them |
59 | | - * to the given `newRequest` function. |
60 | | - * |
61 | | - * @param {Function} newRequest - a function handling requests; it accepts four arguments: |
62 | | - * - proto - a string with the overridden module's protocol name (either `http` or `https`) |
63 | | - * - overriddenRequest - the overridden module's request function already bound to module's object |
64 | | - * - options - the options of the issued request |
65 | | - * - callback - the callback of the issued request |
66 | | - */ |
67 | | -function overrideRequests(newRequest) { |
68 | | - debug('overriding requests') |
69 | | - ;['http', 'https'].forEach(function (proto) { |
70 | | - debug('- overriding request for', proto) |
71 | | - |
72 | | - const moduleName = proto // 1 to 1 match of protocol and module is fortunate :) |
73 | | - const module = require(proto) |
74 | | - const overriddenRequest = module.request |
75 | | - const overriddenGet = module.get |
76 | | - |
77 | | - if (requestOverrides[moduleName]) { |
78 | | - throw new Error( |
79 | | - `Module's request already overridden for ${moduleName} protocol.`, |
80 | | - ) |
81 | | - } |
82 | | - |
83 | | - // Store the properties of the overridden request so that it can be restored later on. |
84 | | - requestOverrides[moduleName] = { |
85 | | - module, |
86 | | - request: overriddenRequest, |
87 | | - get: overriddenGet, |
88 | | - } |
89 | | - // https://nodejs.org/api/http.html#http_http_request_url_options_callback |
90 | | - module.request = function (input, options, callback) { |
91 | | - return newRequest(proto, overriddenRequest.bind(module), [ |
92 | | - input, |
93 | | - options, |
94 | | - callback, |
95 | | - ]) |
96 | | - } |
97 | | - // https://nodejs.org/api/http.html#http_http_get_options_callback |
98 | | - module.get = function (input, options, callback) { |
99 | | - const req = newRequest(proto, overriddenGet.bind(module), [ |
100 | | - input, |
101 | | - options, |
102 | | - callback, |
103 | | - ]) |
104 | | - req.end() |
105 | | - return req |
106 | | - } |
107 | | - |
108 | | - debug('- overridden request for', proto) |
109 | | - }) |
110 | | -} |
111 | | - |
112 | | -/** |
113 | | - * Restores `request` function of `http` and `https` modules to values they |
114 | | - * held before they were overridden by us. |
115 | | - */ |
116 | | -function restoreOverriddenRequests() { |
117 | | - debug('restoring requests') |
118 | | - Object.entries(requestOverrides).forEach( |
119 | | - ([proto, { module, request, get }]) => { |
120 | | - debug('- restoring request for', proto) |
121 | | - module.request = request |
122 | | - module.get = get |
123 | | - debug('- restored request for', proto) |
124 | | - }, |
125 | | - ) |
126 | | - requestOverrides = {} |
127 | | -} |
128 | | - |
129 | 54 | /** |
130 | 55 | * In WHATWG URL vernacular, this returns the origin portion of a URL. |
131 | 56 | * However, the port is not included if it's standard and not already present on the host. |
@@ -621,6 +546,7 @@ function clearTimer(clear, ids) { |
621 | 546 | } |
622 | 547 |
|
623 | 548 | function removeAllTimers() { |
| 549 | + debug('remove all timers') |
624 | 550 | clearTimer(clearTimeout, timeouts) |
625 | 551 | clearTimer(clearImmediate, immediates) |
626 | 552 | } |
@@ -653,6 +579,31 @@ function isRequestDestroyed(req) { |
653 | 579 | ) |
654 | 580 | } |
655 | 581 |
|
| 582 | +/** |
| 583 | + * @param {Request} request |
| 584 | + */ |
| 585 | +function convertFetchRequestToClientRequest(request) { |
| 586 | + const url = new URL(request.url) |
| 587 | + const options = { |
| 588 | + ...urlToOptions(url), |
| 589 | + method: request.method, |
| 590 | + host: url.hostname, |
| 591 | + port: url.port || (url.protocol === 'https:' ? 443 : 80), |
| 592 | + path: url.pathname + url.search, |
| 593 | + proto: url.protocol.slice(0, -1), |
| 594 | + headers: Object.fromEntries(request.headers.entries()), |
| 595 | + } |
| 596 | + |
| 597 | + // By default, Node adds a host header, but for maximum backward compatibility, we are now removing it. |
| 598 | + // However, we need to consider leaving the header and fixing the tests. |
| 599 | + if (options.headers.host === options.host) { |
| 600 | + const { host, ...restHeaders } = options.headers |
| 601 | + options.headers = restHeaders |
| 602 | + } |
| 603 | + |
| 604 | + return new http.ClientRequest(options) |
| 605 | +} |
| 606 | + |
656 | 607 | /** |
657 | 608 | * Returns true if the given value is a plain object and not an Array. |
658 | 609 | * @param {*} value |
@@ -760,12 +711,11 @@ module.exports = { |
760 | 711 | normalizeClientRequestArgs, |
761 | 712 | normalizeOrigin, |
762 | 713 | normalizeRequestOptions, |
763 | | - overrideRequests, |
764 | 714 | percentDecode, |
765 | 715 | percentEncode, |
766 | 716 | removeAllTimers, |
767 | | - restoreOverriddenRequests, |
768 | 717 | setImmediate, |
769 | 718 | setTimeout, |
770 | 719 | stringifyRequest, |
| 720 | + convertFetchRequestToClientRequest, |
771 | 721 | } |
0 commit comments