diff --git a/src/Auth0RestClient.js b/src/Auth0RestClient.js index 79aacded3..92080714b 100644 --- a/src/Auth0RestClient.js +++ b/src/Auth0RestClient.js @@ -27,7 +27,7 @@ class Auth0RestClient { this.wrappedProvider = function (method, args) { if (!this.provider) { - return this.restClient[method](...args); + return this._request(method, args); } let callback; @@ -39,7 +39,7 @@ class Auth0RestClient { .getAccessToken() .then((access_token) => { this.restClient.options.headers['Authorization'] = `Bearer ${access_token}`; - return this.restClient[method](...args); + return this._request(method, args); }) .catch((err) => { if (callback) { @@ -50,6 +50,36 @@ class Auth0RestClient { }; } + _request(method, args) { + if (!this.options.includeResponseHeaders) { + return this.restClient[method](...args); + } + + let callback; + // Handle the case where the promise variant is called without any args + // client.get() -> client.get({}, callback) + if (!args || !args.length) { + args = [{}]; + } + // Handle the case where an undefined placeholder is defined for callback + // client.get(params, undefined) -> client.get(params, callback) + if (typeof args[args.length - 1] === 'undefined') { + args.pop(); + } + if (typeof args[args.length - 1] === 'function') { + callback = args.pop(); + } + return new Promise((resolve, reject) => { + this.restClient[method](...args, (err, data, headers) => { + const payload = { data, headers }; + if (err) { + (callback && callback(err)) || reject(err); + } + (callback && callback(null, payload)) || resolve(payload); + }); + }); + } + getAll(...args) { return this.wrappedProvider('getAll', args); } diff --git a/src/management/BaseManager.js b/src/management/BaseManager.js index 93ec257f9..94bb9dd93 100644 --- a/src/management/BaseManager.js +++ b/src/management/BaseManager.js @@ -25,6 +25,7 @@ class BaseManager { errorFormatter: { message: 'message', name: 'error' }, headers: options.headers, query: { repeatParams: false }, + includeResponseHeaders: options.includeResponseHeaders, }; const usersAuth0RestClient = new Auth0RestClient( diff --git a/src/management/index.js b/src/management/index.js index 99b1365b9..36cfd7865 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -90,6 +90,7 @@ class ManagementClient { * @param {boolean} [options.retry.enabled=true] Enabled or Disable Retry Policy functionality. * @param {number} [options.retry.maxRetries=10] Retry failed requests X times. * @param {object} [options.headers] Additional headers that will be added to the outgoing requests. + * @param {object} [options.includeResponseHeaders] Include the response headers in the payload in the format `{ data, headers }`. */ constructor(options) { if (!options || typeof options !== 'object') { @@ -147,6 +148,7 @@ class ManagementClient { } managerOptions.retry = options.retry; + managerOptions.includeResponseHeaders = options.includeResponseHeaders; /** * Simple abstraction for performing CRUD operations on the diff --git a/test/auth0-rest-client.tests.js b/test/auth0-rest-client.tests.js index a44df6e7c..707bd2457 100644 --- a/test/auth0-rest-client.tests.js +++ b/test/auth0-rest-client.tests.js @@ -228,4 +228,36 @@ describe('Auth0RestClient', () => { done(); }); }); + + it('should include response headers in promise response', async function () { + nock(API_URL).get('/some-resource').reply(200, { data: 'value' }); + + const options = { + includeResponseHeaders: true, + headers: {}, + }; + + const client = new Auth0RestClient(`${API_URL}/some-resource`, options, this.providerMock); + const { data, headers } = await client.getAll(); + expect(data).to.deep.equal({ data: 'value' }); + expect(headers).to.deep.equal({ 'content-type': 'application/json' }); + nock.cleanAll(); + }); + + it('should include response headers in callback response', function (done) { + nock(API_URL).get('/some-resource').reply(200, { data: 'value' }); + + const options = { + includeResponseHeaders: true, + headers: {}, + }; + + const client = new Auth0RestClient(`${API_URL}/some-resource`, options, this.providerMock); + client.getAll((err, { data, headers }) => { + expect(data).to.deep.equal({ data: 'value' }); + expect(headers).to.deep.equal({ 'content-type': 'application/json' }); + nock.cleanAll(); + done(); + }); + }); }); diff --git a/test/management/management-client.tests.js b/test/management/management-client.tests.js index 78c4d89ae..8b38001af 100644 --- a/test/management/management-client.tests.js +++ b/test/management/management-client.tests.js @@ -940,5 +940,29 @@ describe('ManagementClient', () => { expect(this.client.users.assignRoles.called).ok; this.client.users.assignRoles.reset(); }); + + it('should include response headers in response', async function () { + const config = Object.assign({}, withTokenConfig, { includeResponseHeaders: true }); + this.client = new ManagementClient(config); + + nock('https://auth0-node-sdk.auth0.com').get(`/api/v2/users`).reply(200, { data: 'value' }); + + const { data, headers } = await this.client.users.getAll(); + expect(data).to.deep.equal({ data: 'value' }); + expect(headers).to.deep.equal({ 'content-type': 'application/json' }); + nock.cleanAll(); + }); + + it('should include response headers in response for shorthand method', async function () { + const config = Object.assign({}, withTokenConfig, { includeResponseHeaders: true }); + this.client = new ManagementClient(config); + + nock('https://auth0-node-sdk.auth0.com').get(`/api/v2/users`).reply(200, { data: 'value' }); + + const { data, headers } = await this.client.getUsers(); + expect(data).to.deep.equal({ data: 'value' }); + expect(headers).to.deep.equal({ 'content-type': 'application/json' }); + nock.cleanAll(); + }); }); });