Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support http.request signatures added in Node 10.9+ #1588

Merged
merged 10 commits into from Jul 9, 2019

Conversation

mastermatt
Copy link
Member

Fixes #1227
Supersedes #1428

Beginning with v10.9.0, the url parameter can be passed along with a
separate options object to http[s].request, http[s].get, or to the
constructor of ClientRequest. docs

The logic that does the juggling was mostly copied from Node's source.

There was a bit of other cleanup that was committed separately to aid with review.

@paulmelnikow
Copy link
Member

This is great! I can give it a read tomorrow.

@mastermatt mastermatt force-pushed the support-new-request-signature branch from aa4d82c to 9a7ec1b Compare June 18, 2019 16:22
@mastermatt
Copy link
Member Author

fyi @nijynot and @gkalpak

Instead of passing it all around the overrider.
This mimics how the native implementation does it.
Fixes nock#1227

Beginning with v10.9.0, the `url` parameter can be passed along with a
separate options object to `http[s].request`, `http[s].get`, or to the
constructor of `ClientRequest`.

https://nodejs.org/api/http.html#http_http_request_url_options_callback

The logic that does the juggling was mostly copied from Node's source.
@mastermatt mastermatt force-pushed the support-new-request-signature branch from 9a7ec1b to fd54a81 Compare June 23, 2019 03:39
@mastermatt mastermatt added this to In progress in 11.x via automation Jun 23, 2019
@mastermatt
Copy link
Member Author

@paulmelnikow were you able to read through this pr?

@paulmelnikow
Copy link
Member

Ah no, I think I lost track of it. Sorry! I'll aim to take a look tonight or tomorrow!

Copy link
Member

@paulmelnikow paulmelnikow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for this work! I understand most of it, I think, though I left a few questions.

I'll take another pass through thinking about test coverage though this is looking really good.

Sorry it's taken me so long to read this!

lib/common.js Outdated Show resolved Hide resolved
lib/common.js Outdated Show resolved Hide resolved
lib/intercept.js Outdated Show resolved Hide resolved
lib/intercept.js Outdated Show resolved Hide resolved

// The option per the docs is `protocol`. Its unclear if this line is meant to override that and is misspelled or if
// the intend is to explicitly keep track of which module was called using a separate name.
// Either way, `proto` is used as the source of truth from here on out.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what we ought to do here but really appreciate this comment!

res.on('response', callback)
}
return req
return new http.ClientRequest(options, callback)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Object.assign(this, overrider)

if (callback) {
this.once('response', callback)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

lib/intercept.js Show resolved Hide resolved
lib/recorder.js Show resolved Hide resolved
mastermatt and others added 2 commits July 8, 2019 11:34
Co-Authored-By: Paul Melnikow <github@paulmelnikow.com>
@@ -453,3 +453,28 @@ test('percentEncode encodes extra reserved characters', t => {
t.equal(common.percentEncode('foo+(*)!'), 'foo%2B%28%2A%29%21')
t.done()
})

test('normalizeClientRequestArgs throws for invalid URL', async t => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gr2m has expressed a preference for testing our helper functions through real use cases in the public API wherever possible, and it seems to pay off well. It also has the advantage of surfacing code that is no longer needed.

Would you be up for expressing these tests in terms of calls to http?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please 👍

scope.done()
t.done()
})
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

tests/test_intercept.js Show resolved Hide resolved
Copy link
Member

@gr2m gr2m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update the docs to mention the new request signature?

@paulmelnikow
Copy link
Member

Could you update the docs to mention the new request signature?

This PR doesn't change the documented API, rather it makes the mock surface compatible with Node 10.9+ (#1227).

I don't think we have documentation of the supported mock surface, beyond the tests. We could add some, though I don't think it needs to be in this PR.

@gr2m
Copy link
Member

gr2m commented Jul 8, 2019

Okay, thank you for the clarification

@paulmelnikow paulmelnikow changed the title feat: Support new request signature feat: Support http.request signatures added in Node 10.9+ Jul 8, 2019
@mastermatt
Copy link
Member Author

I believe I've addressed all the comments.
@gr2m @paulmelnikow could I get another pass from you?

paulmelnikow added a commit that referenced this pull request Jul 8, 2019
Ref #1404 (comment)

This leaves intact two missed coverage spots in `lib/recorder.js` which are being taken care of in #1588.

Also ref #1607
tests/test_common.js Outdated Show resolved Hide resolved
tests/test_common.js Outdated Show resolved Hide resolved
Copy link
Member

@paulmelnikow paulmelnikow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to merge when ready!

@mastermatt mastermatt merged commit e3e6a65 into nock:beta Jul 9, 2019
11.x automation moved this from In progress to Done Jul 9, 2019
@mastermatt mastermatt deleted the support-new-request-signature branch July 9, 2019 05:32
@nockbot
Copy link
Collaborator

nockbot commented Jul 9, 2019

🎉 This PR is included in version 11.0.0-beta.22 🎉

The release is available on:

Your semantic-release bot 📦🚀

@nockbot
Copy link
Collaborator

nockbot commented Aug 12, 2019

🎉 This PR is included in version 11.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

gr2m pushed a commit that referenced this pull request Sep 4, 2019
Ref #1404 (comment)

This leaves intact two missed coverage spots in `lib/recorder.js` which are being taken care of in #1588.

Also ref #1607
gr2m pushed a commit that referenced this pull request Sep 4, 2019
* Allow three arg form of `request` and `ClientRequest`.

Fixes #1227

Beginning with v10.9.0, the `url` parameter can be passed along with a
separate options object to `http[s].request`, `http[s].get`, or to the
constructor of `ClientRequest`.

https://nodejs.org/api/http.html#http_http_request_url_options_callback

The logic that does the juggling was mostly copied from Node's source.

* Remove unnecessary overrider in intercept.

* Register ClientRequest callback on response event.

Instead of passing it all around the overrider.
This mimics how the native implementation does it.
gr2m pushed a commit that referenced this pull request Sep 4, 2019
Ref #1404 (comment)

This leaves intact two missed coverage spots in `lib/recorder.js` which are being taken care of in #1588.

Also ref #1607
gr2m pushed a commit that referenced this pull request Sep 4, 2019
* Allow three arg form of `request` and `ClientRequest`.

Fixes #1227

Beginning with v10.9.0, the `url` parameter can be passed along with a
separate options object to `http[s].request`, `http[s].get`, or to the
constructor of `ClientRequest`.

https://nodejs.org/api/http.html#http_http_request_url_options_callback

The logic that does the juggling was mostly copied from Node's source.

* Remove unnecessary overrider in intercept.

* Register ClientRequest callback on response event.

Instead of passing it all around the overrider.
This mimics how the native implementation does it.
gr2m pushed a commit that referenced this pull request Sep 5, 2019
Ref #1404 (comment)

This leaves intact two missed coverage spots in `lib/recorder.js` which are being taken care of in #1588.

Also ref #1607
gr2m pushed a commit that referenced this pull request Sep 5, 2019
* Allow three arg form of `request` and `ClientRequest`.

Fixes #1227

Beginning with v10.9.0, the `url` parameter can be passed along with a
separate options object to `http[s].request`, `http[s].get`, or to the
constructor of `ClientRequest`.

https://nodejs.org/api/http.html#http_http_request_url_options_callback

The logic that does the juggling was mostly copied from Node's source.

* Remove unnecessary overrider in intercept.

* Register ClientRequest callback on response event.

Instead of passing it all around the overrider.
This mimics how the native implementation does it.
)
// https://nodejs.org/api/http.html#http_http_get_options_callback
module.get = function(input, options, callback) {
const req = module.request(input, options, callback)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not calling newRequest instead? This breaks the Node API as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done to mimic native Node behavior in case other libs are monkey-patching the function.
Can you provide more details on "This breaks the Node API as well"? Preferably in a new issue.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make a new issue. But writing the details here as well.

New Relic (https://github.com/newrelic/node-newrelic) is overwriting http.get and http.request like you do. But when http.get is calling http.request like here, a call to http.get will call http.request twice when using nock in a New Relic test.

To prove that this is not native Node behaviour (at least on Node 12):

const http = require('http');

function request() {
  console.log('http.request', arguments);
}

http.request = request;

// our request function is not called
http.get('http://google.com', () => {});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
11.x
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

5 participants