Request & Response Interceptors
What they are and why to use them
I mentioned in one of my previous posts the use of requestInterceptors
and responseInterceptors
as a way to help manage your storage attributes. Today we’re going to take a deeper dive into this and how it can help your development flow.
So first of all I hope the names of these two handlers are actually pretty clear. The requestInterceptor
intercepts every request made to your skill before it hits a handler and the responseInterceptor
intercepts every response your skill is going to send prior to being sent.
This means you can run common code on every request
and every response
.
Both the requestInterceptor
and responseInterceptor
should have a function process(handlerInput)
So like your intentHandlers canHandle
and handle
functions, process
has access to the handlerInput
variable and so can access the current request, attributesManager
etc.
The benefit of this is that in your requestInterceptor
you can now merge persistentAttributes
with your sessionAttributes
without having to do it in every intentHandler, and thus follow the DRY principles. A sample requestInterceptor
might look like this.
All we’re really doing here through lines 4–9 is getting the current sessionAttributes
then getting the current persistentAttributes
and using Object.assign()
to merge both objects into the sessionAttributes
and finally on line 9 calling setSessionAttributes
to make sure they are saved to the current sessionAttributes
. Object.assign
uses the order of objects passed in when merging the objects, so later objects will overwrite any existing properties of the same name. In this case, if we had persistentAttributes.foo
and sessionAttributes.foo
the value of sessionAttributes.foo
would take priority as it comes last in the Object.merge
function. This is what we would most likely want, with sessionAttributes
probably being more fresh than our persistentAttributes.
ResponseInterceptors
are useful in the opposite way. After any of your code has run, you can then save all your sessionAttributes back into persistentAttributes to make sure they’re stored across sessions.
As you can see, this is very similar to our requestInterceptor
the only difference really being on lines 12 and 13, where we set our persistentAttributes
equal to the result of the Object.assign
and then save it back to the persistent storage.
Finally we then make sure we return the handlerInput.getResponse()
call.
You will notice I’ve marked both the process methods as async
this is because I make use of async/await
when saving and getting the persistent attributes. You could of course use apromise
here, but I like the async/await
syntax.
Finally to make sure your requestInterceptor
and responseInterceptor
actually run, you need to add them to your lambda exports. This can be done like follows:
exports.handler = Alexa.SkillBuilders.custom(). .addRequestInterceptors(RequestInterceptor).addResponseInterceptors(ResponseInterceptor).lambda();
Once again, feel free to join my new Facebook group around Alexa Skills Dev to ask any questions and share any skills you might want feedback with. Or if you want a tutorial on a particular subject of Alexa Skills development, let me know.
Thanks for reading.