Originally published on strongloop.com
Wondering what an interceptor is in LoopBack 4?
Interceptors are reusable functions to provide aspect-oriented logic around method invocations.
Seems pretty useful, right? There are 3 levels of interceptors: global, class level and method level. In this article, we are going to look into what a global interceptor is and how to use it.
Global interceptors are automatically called for all controller methods. They are called first, before interceptors specified at class and method level. You can insert additional logic before and after method invocation through interceptors. Examples of using global interceptors are caching and authorization.
For the sake of illustration, we'll use global interceptors for logging purposes using the default /ping
endpoint that comes with all scaffolded LB4 application. Note that interceptors are not the best tool for logging. It's usually better to implement logging as a new sequence action, as we demonstrate in our log extension example.
Creating a Global Interceptor
After you've scaffolded the application, run lb4 interceptor
command to create an interceptor. Since we are going to have one global interceptor, leave the group name for the global interceptor
as an empty string which is the default value.
$ lb4 interceptor
? Interceptor name: logging
? Is it a global interceptor? Yes
Global interceptors are sorted by the order of an array of group names bound
to ContextBindings.GLOBAL_INTERCEPTOR_ORDERED_GROUPS. See
https://loopback.io/doc/en/lb4/Interceptors.html#order-of-invocation-for-interceptors.
? Group name for the global interceptor: ('')
create src/interceptors/logging.interceptor.ts
update src/interceptors/index.ts
Interceptor Logging was created in src/interceptors/
Adding Logic to the Logging Interceptor
Let's take a look at the generated interceptor.
Go to src/interceptors/logging.interceptor.ts
. You'll see two comments in the try-catch block where you can add your logic: pre-invocation and post-invocation. We are going to simply print out the method name of the invocationContext before and after the method is being invoked.
try {
// Add pre-invocation logic here
// ----- ADDED THIS LINE ----
console.log('log: before-' + invocationCtx.targetName);
const result = await next();
// Add post-invocation logic here
// ----- ADDED THIS LINE -----
console.log('log: after-' + invocationCtx.targetName);
return result;
} catch (err) {
// Add error handling logic here
console.error(err);
throw err;
}
Global Interceptor in Action
That's it! The global interceptor is ready for action.
Start the application with npm start
command. Then go to the API Explorer: http://localhost:3000/explorer.
You'll now see the following printed to the console:
log: before-ExplorerController.prototype.index
log: after-ExplorerController.prototype.index
Next, call the /ping
endpoint by clicking "Try it Out" > "Execute". You'll see two more lines got printed:
log: before-PingController.prototype.ping
log: after-PingController.prototype.ping
The interceptor method was called because it is at the global level.
Getting HttpRequest from InvocationContext
For more meaningful log messages, you might want to get more information about the HTTP request. To do that, add this import in the interceptor class:
import {RestBindings} from '@loopback/rest';
We're going to print out the endpoint being called. To do that, add the snippet below as the pre-invocation logic:
const httpReq = await invocationCtx.get(RestBindings.Http.REQUEST, {optional: true,});
if (httpReq) {
console.log('Endpoint being called:', httpReq.path);
}
Restart the application, go to API Explorer and call the /ping
endpoint again. You'll see the following printed to the console log:
log: before-ExplorerController.prototype.index
Endpoint being called: /explorer/
log: after-ExplorerController.prototype.index
log: before-PingController.prototype.ping
Endpoint being called: /ping
log: after-PingController.prototype.ping
Other Resources
For other interceptor examples, check out: https://loopback.io/doc/en/lb4/Interceptors.html#example-interceptors
For running applications that use interceptors, see:
- Caching enabled via interceptors in Greeter application, https://github.com/strongloop/loopback-next/tree/master/examples/greeting-app
- Authorization added using interceptors in this tutorial, https://strongloop.com/strongblog/building-an-online-game-with-loopback-4-pt4/
Call to Action
LoopBack's future success depends on you. We appreciate your continuous support and engagement to make LoopBack even better and meaningful for your API creation experience. Please join us and help the project by:
- Reporting issues.
- Contributing code and documentation.
- Opening a pull request on one of our "good first issues".
- Joining our user group.