Skip to content

Commit

Permalink
Future proof interceptor argument signatures
Browse files Browse the repository at this point in the history
The third argument to the request/response callbacks for an interceptor
was previously a reference to the current client. Now it's a hash, which
in turn contains the client. The raw client arguments are also available
on that hash.

As other properties are injected into the interceptor callbacks, they will
be added to this hash instead rather than using positional arguments.
  • Loading branch information
scothis committed Aug 28, 2013
1 parent e894895 commit 09c4c34
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 19 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ Change Log
.next
- JSON HAL mime serializer for application/hal+json
- CSRF protection interceptor
- the third argument to the interceptor request/response callbacks is not an object instead of the client, the client is a property on that object
- HATEOAS interceptor defaults to indexing relationships directly on the host entity instead of the '_links' child object. A child object may still be configured.
- HATEOAS interceptor returns same promise on multiple relationship property accesses
- support bower 0.10+, older versions of bower will no longer work
Expand Down
14 changes: 8 additions & 6 deletions docs/interceptors.md
Original file line number Diff line number Diff line change
Expand Up @@ -942,19 +942,19 @@ noopInterceptor = interceptor({
// do studd with the config
return config;
},
request: function (request, config) {
request: function (request, config, meta) {
// do stuff with the request
return request;
},
response: function (response, config, client) {
response: function (response, config, meta) {
// do stuff with the response
return response;
},
success: function (response, config, client) {
success: function (response, config, meta) {
// do stuff with the response
return response;
},
error: function (response, config, client) {
error: function (response, config, meta) {
// do stuff with the response
return response;
}
Expand All @@ -973,17 +973,19 @@ delayRequestInterceptor = interceptor({
});
```
The `meta` argument contains additional information about the context of the request. It contains the `client`, which can be used to make subsequent requests, and the raw `arguments` provided to the client.
For interceptors that need to track state between request and response handlers, the context of each handler is shared and unique to each invocation.
```javascript
interceptor = require('rest/interceptor');
counter = 0;
countLoggingInterceptor = interceptor({
request: function (request, config) {
request: function (request) {
this.count = counter++;
return request;
},
response: function (response, config, client) {
response: function (response) {
console.log('invocation count: ', this.count);
return response;
}
Expand Down
14 changes: 8 additions & 6 deletions interceptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@
return config;
}

function defaultRequestHandler(request /*, config */) {
function defaultRequestHandler(request /*, config, meta */) {
return request;
}

function defaultResponseHandler(response /*, config, client */) {
function defaultResponseHandler(response /*, config, meta */) {
return response;
}

Expand Down Expand Up @@ -111,11 +111,13 @@
config = initHandler(beget(config));

client = function (request) {
var context = {};
var context, meta;
context = {};
meta = { 'arguments': Array.prototype.slice.call(arguments), client: client };
request = typeof request === 'string' ? { path: request } : request || {};
request.originator = request.originator || client;
return when(
requestHandler.call(context, request, config),
requestHandler.call(context, request, config, meta),
function (request) {
var response, abort, next;
next = target;
Expand All @@ -131,10 +133,10 @@
return when(
next(request),
function (response) {
return successResponseHandler.call(context, response, config, client);
return successResponseHandler.call(context, response, config, meta);
},
function (response) {
return errorResponseHandler.call(context, response, config, client);
return errorResponseHandler.call(context, response, config, meta);
}
);
});
Expand Down
4 changes: 2 additions & 2 deletions interceptor/hateoas.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@
config.target = config.target || '';
return config;
},
response: function (response, config, hateoas) {
response: function (response, config, meta) {
var client;

client = config.client || (response.request && response.request.originator) || hateoas;
client = config.client || (response.request && response.request.originator) || meta.client;

function apply(target, links) {
links.forEach(function (link) {
Expand Down
4 changes: 2 additions & 2 deletions interceptor/retry.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
config.max = config.max || Infinity;
return config;
},
error: function (response, config, client) {
error: function (response, config, meta) {
var request;

request = response.request;
Expand All @@ -48,7 +48,7 @@
return when.reject({ request: request, error: 'precanceled' });
}
request.retry = Math.min(request.retry * config.multiplier, config.max);
return client(request);
return meta.client(request);
});
}
});
Expand Down
31 changes: 28 additions & 3 deletions test/interceptor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,17 +406,42 @@
})
);
},
'should have access to the client in the response handlers for subsequent requests': function () {
'should have access to the client for subsequent requests': function () {
var theInterceptor, client;
theInterceptor = interceptor({
response: function (response, config, client) {
response.client = client;
request: function (request, config, meta) {
request.client = meta.client;
return request;
},
response: function (response, config, meta) {
response.client = meta.client;
return response;
}
});
client = theInterceptor(defaultClient);
return client().then(function (response) {
assert.same(client, response.client);
assert.same(client, response.request.client);
assert.same('default', response.id);
}).otherwise(fail);
},
'should have access to the invocation args': function () {
var theInterceptor, client;
theInterceptor = interceptor({
request: function (request, config, meta) {
request['arguments'] = meta['arguments'];
return request;
},
response: function (response, config, meta) {
response['arguments'] = meta['arguments'];
return response;
}
});
client = theInterceptor(defaultClient);
return client('foo', 'bar').then(function (response) {
assert.same('foo', response['arguments'][0]);
assert.same('bar', response['arguments'][1]);
assert.same(response['arguments'], response.request['arguments']);
assert.same('default', response.id);
}).otherwise(fail);
},
Expand Down

0 comments on commit 09c4c34

Please sign in to comment.