Skip to content
This repository has been archived by the owner on Sep 8, 2023. It is now read-only.

fix: honor request options #50

Merged
merged 4 commits into from
Aug 14, 2020

Conversation

leonsomed
Copy link
Contributor

Description

This PR enforces honoring on queryParams, pathParams, and header like it was supported in version < 2.1.1.

Motivation and Context

Previous to version 2.1.1 queryParams, pathParams, and header were honored to remain as the options that were explicitly passed to the request method. However, version 2.1.1 introduces a change where it will initialize queryParams, pathParams, and header to an empty object when they are not passed to the request method.

The behavior described above causes an issue with requests that contain queryParams in the path. For example: /users?lucky=true, this path contains an embeded queryParam but it will be stripped away before the execution because it is not included in the queryParams object. Prior to version 2.1.1 this was not a problem because an undefined queryParams will be ignored, however after version 2.1.1 an undefined queryParams will be initialized to an empty object and it will cause the removal of the embedded lucky query param.

The reason this is important is because there are APIs that respond with link resources with embedded queryParams.

How Has This Been Tested?

Previously this call will strip away the lucky query param
client.request({ method: 'GET', path: '/users?lucky=true' });

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

honor the case when no queryParams are passed instead of initializing them to an empty object
Copy link
Member

@tuckbick tuckbick left a comment

Choose a reason for hiding this comment

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

Good catch! I prefer making the change here like you've done as opposed to checking if the options are empty before operating on them: https://github.com/ExpediaGroup/service-client/blob/master/lib/http/request.js#L187-L203

I ran a couple benchmarks for the different ways to go about this change:

For the sake of being more clear (and given the test results above), can you implement the more explicit code seen in the 3rd case test case in the links above?

We'll get this added to the 2.x version too once this is merged in.

Leonso added 2 commits August 12, 2020 17:48
ensure original query params in path are preserved even if a query params object is passed to the request
@leonsomed
Copy link
Contributor Author

leonsomed commented Aug 13, 2020

The only affected option is queryParams both pathParams and header do not get affected.
After further analysis I realized queryParams were not being stripped but instead they were being obscured by an additional query string, ie:

// this requests the following path, notice the double start query string character: ?

client.request({ method: 'GET', path: '/users?lucky=true', queryParams: {} });
// /users?lucky=true?

client.request({ method: 'GET', path: '/users?lucky=true', queryParams: { test: true } });
// /users?lucky=true?test=true

So the new approach ensures not breaking the existing query string in path, if it exists, ie:

client.request({ method: 'GET', path: '/users?lucky=true', queryParams: {} });
// /users?lucky=true&

client.request({ method: 'GET', path: '/users?lucky=true', queryParams: { test: true } });
// /users?lucky=true&test=true

@@ -190,7 +190,7 @@ const create = async function (method, path, options, hooks = {}) {
})

if (options.queryParams) {
path += `?${QueryString.stringify(options.queryParams)}`
path += `${path.includes('?') ? '&' : '?'}${QueryString.stringify(options.queryParams)}`
Copy link
Member

Choose a reason for hiding this comment

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

I think we also need to account for if path already ends in a &. We wouldn't want to have ?foo=bar&&fizz=buzz.

Some options to address this:

  • strip any trailing & before processing anything
  • don't add a & if one already exists
  • parse the path's query string into an object, merge options.queryParams into the object, then stringify and re-attach to the path

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i took the third approach

refactor to merge queryParams from path and from options
Copy link
Member

@tuckbick tuckbick left a comment

Choose a reason for hiding this comment

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

Thanks! This is great! I'll get this merged and released in v2 and v3 asap.

@tuckbick tuckbick merged commit 448e7d8 into ExpediaGroup:master Aug 14, 2020
tuckbick pushed a commit that referenced this pull request Aug 17, 2020
* honor request options

honor the case when no queryParams are passed instead of initializing them to an empty object

* Revert "honor request options"

This reverts commit 686d001.

* fix-honor-requests-options

ensure original query params in path are preserved even if a query params object is passed to the request

* refactor

refactor to merge queryParams from path and from options

Co-authored-by: Leonso <[email protected]>
@tuckbick
Copy link
Member

@leonsomed Released in v2.1.2 and v3.0.1.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants