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

nock mixes usage of qs and querystring #507

Closed
jeffora opened this issue Mar 22, 2016 · 7 comments
Closed

nock mixes usage of qs and querystring #507

jeffora opened this issue Mar 22, 2016 · 7 comments

Comments

@jeffora
Copy link

jeffora commented Mar 22, 2016

It appears nock mixes usage of native node querystring module and npm installed qs module for parsing querystring-like objects.

In nock/lib/interceptor.js it requires qs (a dependency in package.json), but in nock/lib/match_body.js it requires querystring, the native node library.

These two libraries have different outputs. For example:

var query = require('querystring');
var qs = require('qs');

query.parse('a%5Bb%5D=test'); // => { 'a[b]': 'test' }
qs.parse('a%5Bb%5D=test'); // => { a: { b: 'test' } }

This means interceptors and body matchers have different behavior.

@pgte
Copy link
Member

pgte commented Mar 25, 2016

@jeffora Good catch.

A PR would be welcome..

xavierchow added a commit to xavierchow/nock that referenced this issue May 22, 2016
@stale
Copy link

stale bot commented Sep 17, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. We try to do our best, but nock is maintained by volunteers and there is only so much we can do at a time. Thank you for your contributions.

@stale stale bot added the stale label Sep 17, 2018
@gr2m gr2m added the pinned label Sep 20, 2018
@stale stale bot removed the stale label Sep 20, 2018
@AJamesPhillips
Copy link

Which dependency would be desirable to keep? 'querystring' or 'qs' ?

@kbakba
Copy link

kbakba commented Jan 10, 2019

Which dependency would be desirable to keep? 'querystring' or 'qs' ?

I think native 'querystring'

see #563 (comment)

@paulmelnikow
Copy link
Member

I think this is a good idea, though it will be a breaking change to body matching. For example, It will break use cases like this one:

test('array like urlencoded form posts are correctly parsed', function(t) {
nock('http://example.test')
.post('/', {
arrayLike: [
{
fieldA: '0',
fieldB: 'data',
fieldC: 'value',
},
],
})
.reply(200)
mikealRequest(
{
url: 'http://example.test',
method: 'post',
form: {
'arrayLike[0].fieldA': '0',
'arrayLike[0].fieldB': 'data',
'arrayLike[0].fieldC': 'value',
},
},
function(err, res) {
if (err) throw err
assert.equal(res.statusCode, 200)
t.end()
}
)
})

I suggest we add a flag to allow users who use array syntax and qs-style encoding to keep using it. We could make qs an optionalDependency.

mastermatt added a commit to mastermatt/nock that referenced this issue Jul 18, 2019
Drop `deep-equal` and `qs` dependency.

Replace `qs.parse` with `querystring.parse` from the std lib.
The main difference between the two being that `qs` "unpacks" nested
objects when the search keys use JSON path notation eg "foo[bar][0]".
This has no affect on URL encoded form bodies during matching because
we manually convert the notation to nested objects for comparison now,
which means users can now provide expectations in either form.
Similarly, when matching search params using a provided object, there
is no net affect. The only breaking change is when a user provides a
callback function to `.query()`.

Replace `deep-equal` with a custom utility function in common.js.
Doing so not only dropped a dependency, it also achieved a more generic
utility for our usec ase with less code.

Interceptor matching had some refactoring:
- Query matching was moved to its own method in an effort to isolate concerns.
- Matching the request method was moved to the top of the match method.
- Debugging statements were updated as a baby step towards having more insight into why a match was missed.

Fixes nock#507
Fixes nock#1552

BREAKING CHANGE: The only argument passed to the Interceptor.query
callback now receives the output from querystring.parse instead of
qs.parse. This means that instead of nested objects the argument will
be a flat object.
mastermatt added a commit that referenced this issue Jul 28, 2019
* refactor(match_body): options obj as arg instead of context

Also don't bother calling `transformRequestBodyFunction` or `matchBody`
if there is no request body on the Interceptor.

* perf: prefer regexp.test over match when applicable

* refactor: overhaul body and query matching

Drop `deep-equal` and `qs` dependency.

Replace `qs.parse` with `querystring.parse` from the std lib.
The main difference between the two being that `qs` "unpacks" nested
objects when the search keys use JSON path notation eg "foo[bar][0]".
This has no affect on URL encoded form bodies during matching because
we manually convert the notation to nested objects for comparison now,
which means users can now provide expectations in either form.
Similarly, when matching search params using a provided object, there
is no net affect. The only breaking change is when a user provides a
callback function to `.query()`.

Replace `deep-equal` with a custom utility function in common.js.
Doing so not only dropped a dependency, it also achieved a more generic
utility for our usec ase with less code.

Interceptor matching had some refactoring:
- Query matching was moved to its own method in an effort to isolate concerns.
- Matching the request method was moved to the top of the match method.
- Debugging statements were updated as a baby step towards having more insight into why a match was missed.

Fixes #507
Fixes #1552

BREAKING CHANGE: The only argument passed to the Interceptor.query
callback now receives the output from querystring.parse instead of
qs.parse. This means that instead of nested objects the argument will
be a flat object.
@nockbot
Copy link
Collaborator

nockbot commented Jul 28, 2019

🎉 This issue has been resolved in version 11.0.0-beta.30 🎉

The release is available on:

Your semantic-release bot 📦🚀

@nockbot
Copy link
Collaborator

nockbot commented Aug 13, 2019

🎉 This issue has been resolved in version 11.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

gr2m pushed a commit that referenced this issue Sep 4, 2019
* refactor(match_body): options obj as arg instead of context

Also don't bother calling `transformRequestBodyFunction` or `matchBody`
if there is no request body on the Interceptor.

* perf: prefer regexp.test over match when applicable

* refactor: overhaul body and query matching

Drop `deep-equal` and `qs` dependency.

Replace `qs.parse` with `querystring.parse` from the std lib.
The main difference between the two being that `qs` "unpacks" nested
objects when the search keys use JSON path notation eg "foo[bar][0]".
This has no affect on URL encoded form bodies during matching because
we manually convert the notation to nested objects for comparison now,
which means users can now provide expectations in either form.
Similarly, when matching search params using a provided object, there
is no net affect. The only breaking change is when a user provides a
callback function to `.query()`.

Replace `deep-equal` with a custom utility function in common.js.
Doing so not only dropped a dependency, it also achieved a more generic
utility for our usec ase with less code.

Interceptor matching had some refactoring:
- Query matching was moved to its own method in an effort to isolate concerns.
- Matching the request method was moved to the top of the match method.
- Debugging statements were updated as a baby step towards having more insight into why a match was missed.

Fixes #507
Fixes #1552

BREAKING CHANGE: The only argument passed to the Interceptor.query
callback now receives the output from querystring.parse instead of
qs.parse. This means that instead of nested objects the argument will
be a flat object.
gr2m pushed a commit that referenced this issue Sep 4, 2019
* refactor(match_body): options obj as arg instead of context

Also don't bother calling `transformRequestBodyFunction` or `matchBody`
if there is no request body on the Interceptor.

* perf: prefer regexp.test over match when applicable

* refactor: overhaul body and query matching

Drop `deep-equal` and `qs` dependency.

Replace `qs.parse` with `querystring.parse` from the std lib.
The main difference between the two being that `qs` "unpacks" nested
objects when the search keys use JSON path notation eg "foo[bar][0]".
This has no affect on URL encoded form bodies during matching because
we manually convert the notation to nested objects for comparison now,
which means users can now provide expectations in either form.
Similarly, when matching search params using a provided object, there
is no net affect. The only breaking change is when a user provides a
callback function to `.query()`.

Replace `deep-equal` with a custom utility function in common.js.
Doing so not only dropped a dependency, it also achieved a more generic
utility for our usec ase with less code.

Interceptor matching had some refactoring:
- Query matching was moved to its own method in an effort to isolate concerns.
- Matching the request method was moved to the top of the match method.
- Debugging statements were updated as a baby step towards having more insight into why a match was missed.

Fixes #507
Fixes #1552

BREAKING CHANGE: The only argument passed to the Interceptor.query
callback now receives the output from querystring.parse instead of
qs.parse. This means that instead of nested objects the argument will
be a flat object.
gr2m pushed a commit that referenced this issue Sep 5, 2019
* refactor(match_body): options obj as arg instead of context

Also don't bother calling `transformRequestBodyFunction` or `matchBody`
if there is no request body on the Interceptor.

* perf: prefer regexp.test over match when applicable

* refactor: overhaul body and query matching

Drop `deep-equal` and `qs` dependency.

Replace `qs.parse` with `querystring.parse` from the std lib.
The main difference between the two being that `qs` "unpacks" nested
objects when the search keys use JSON path notation eg "foo[bar][0]".
This has no affect on URL encoded form bodies during matching because
we manually convert the notation to nested objects for comparison now,
which means users can now provide expectations in either form.
Similarly, when matching search params using a provided object, there
is no net affect. The only breaking change is when a user provides a
callback function to `.query()`.

Replace `deep-equal` with a custom utility function in common.js.
Doing so not only dropped a dependency, it also achieved a more generic
utility for our usec ase with less code.

Interceptor matching had some refactoring:
- Query matching was moved to its own method in an effort to isolate concerns.
- Matching the request method was moved to the top of the match method.
- Debugging statements were updated as a baby step towards having more insight into why a match was missed.

Fixes #507
Fixes #1552

BREAKING CHANGE: The only argument passed to the Interceptor.query
callback now receives the output from querystring.parse instead of
qs.parse. This means that instead of nested objects the argument will
be a flat object.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants