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

Commit

Permalink
Feature: add support for a read hook (#63)
Browse files Browse the repository at this point in the history
* Fix: setting up graphql error processing

* Adding support for oAuth for graphql

* Other: docs

* Fix: test

* Fix: test

* removing code because we are handling the graphql oauth as read:true

* Fix: consolidating and renaming

* Fix: cleanup

* Feature: changelog

Co-authored-by: Anthony Lauro <[email protected]>
Co-authored-by: Anthony Lauro <[email protected]>
  • Loading branch information
3 people authored Sep 29, 2021
1 parent 27380eb commit 3c6ec65
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Unreleased

#### Feature

* add support for a read hook ([#63](https://github.com/ExpediaGroup/service-client/pull/63))

## [3.1.0](https://github.com/expediagroup/service-client/compare/v3.0.1...v3.1.0) (2021-09-09)

#### Feature
Expand Down
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ Service-Client plugins provide the ability to hook into different spots of a req
Plugins are registered with `ServiceClient.mergeConfig({plugins: []})` or `ServiceClient.use([])` and affect all Service-Client instances created thereafter.

### Overview
A plugin exports a function which, when executed, returns an object containing a set of hook functions to be ran during a request's lifecycle. See all available hooks [below](#available-plugins).
A plugin exports a function which, when executed, returns an object containing a set of hook functions to be run during a request's lifecycle. See all available hooks [below](#available-plugins).

Example:
```js
Expand Down Expand Up @@ -322,7 +322,7 @@ async function plugin({client, context, plugins}) {
* This hook is special. The only value that should be returned here is
* a response object. This is helpful for authentication plugins that
* want to retry a request if an invalid response was received. A request
* made within this hook could return it's response object here.
* made within this hook could return its response object here.
*
* There's a catch however. Since response objects from multiple hooks
* cannot be merged, only the first response object will be taken. All
Expand All @@ -335,6 +335,24 @@ async function plugin({client, context, plugins}) {

},

/**
* This hook is special. This hook behaves just like response but can be used to
* validate data after being read. The only value that should be returned here is
* a response object. This is helpful for authentication plugins that
* want to retry a request if an invalid response was received. A request
* made within this hook could return its response object here.
*
* There's a catch however. Since response objects from multiple hooks
* cannot be merged, only the first response object will be taken. All
* other returned responses are discarded.
*
* @param {object} data - data provided to the hook on every request
* @param {object} data.response - the response received from Wreck after being read
*/
async read(data) {

},

/**
* @param {object} data - data provided to the hook on every request
* @param {Error} data.error - the error object resulting from timeouts, read errors, etc
Expand Down
5 changes: 5 additions & 0 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ class ServiceClient {
await hooks.error({ context, clientId, requestId, ts, servicename, operation, error })
}
}
if (hooks.read) {
reqHooks.read = async (id, response, ts = Date.now()) => {
return hooks.read({ context, clientId, requestId, ts, servicename, operation, response })
}
}

const doRequest = async function () {
if (self._circuitState.open) {
Expand Down
9 changes: 8 additions & 1 deletion lib/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,20 @@ async function init (options) {

return finalData
} else

// for the `response` hook, return the first non-falsy value
if (hookName === 'response') {
const response = results.find((result) => result)

debug('%s(): first result: %j', hookName, response)

return response
} else
// for the `read` hook, return the first non-falsy value
if (hookName === 'read') {
const response = results.find((result) => result)

debug('%s(): first result: %j', hookName, response)

return response
}
}
Expand Down
7 changes: 6 additions & 1 deletion lib/http/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ const makeRequest = async function (method, path, options, hooks) {
return response
}

response.payload = await Read(response, options.readOptions)
if (response.payload === undefined) {
response.payload = await Read(response, options.readOptions)
if (hooks.read) {
response = await hooks.read(options.id, response) || response
}
}

debug('makeRequest(): payload read')
oncomplete()
Expand Down
6 changes: 4 additions & 2 deletions test/unit/hooks/standalone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ describe('Using ServiceClient in a standalone context', () => {
response: suite.sandbox.spy(),
error: suite.sandbox.spy(),
stats: suite.sandbox.spy(),
end: suite.sandbox.spy()
end: suite.sandbox.spy(),
read: suite.sandbox.spy()
}
ServiceClient.use(() => {
return spies
Expand All @@ -65,8 +66,9 @@ describe('Using ServiceClient in a standalone context', () => {
Sinon.assert.notCalled(spies.error) // no error for this test
Sinon.assert.calledOnce(spies.stats)
Sinon.assert.calledOnce(spies.end)
Sinon.assert.calledOnce(spies.read)

Sinon.assert.callOrder(spies.request, spies.init, spies.socket, spies.response, spies.stats, spies.end)
Sinon.assert.callOrder(spies.request, spies.init, spies.socket, spies.response, spies.read, spies.stats, spies.end)
})

it('should call hooks (error thrown in plugin initialization)', async function () {
Expand Down

0 comments on commit 3c6ec65

Please sign in to comment.