Guarding URL variables using Aspect Oriented Programming

For the last several years I’ve been working mainly on REST APIs for SaaS businesses and I’ve seen one pattern reoccur a lot— limiting/validating certain rules based on URL variables. In this post I’d like to show you how can you solve this problem using Aspect Oriented Programming (AOP).
The problem
I was developing a REST API for Help Scout’s ticket system where we needed to filter out tickets by company ID and users that belong to the company for incoming requests. I want to show you, the reader, the thought process I went through. So pull up a chair and let’s pair together to solve the problem.
Starting out with a simple solution
Let’s try to think of the simplest thing we can do to solve the problem above. We’re going to pass companyId
and userId
values to the URL as URL variables. Before the actual logic that fetches the desired tickets is executed, the system needs to ensure that a couple of preconditions are met:
companyId
exists within the systemuserId
exists within the systemuserId
belongs to the company withcompanyId
We’re going to use Spring Boot with REST Assured tests for these examples, but it should be easy to adapt this solution in to other web-based frameworks.
The API will expose a route /companyId/userId/tickets
and we want to make sure that all preconditions above are met. Let’s start with designing a few tests:
We could make them pass with controller code like this (using Spring MVC):
Evolving the solution — DRYing it up
While this works just fine for a small problem, we would need to DRY this up a bit if we wanted to use this pattern on multiple routes in multiple controllers that include companyId
and userId
. We would want to ensure that they are all properly checked.
One option would be extracting this logic into a custom component, or pushing it up into a base controller, perhaps like so:
An advantage of this approach is that the logic is easily re-usable across various controllers. On the downside, we have to remember to invoke the check manually. I suppose it isn’t a big deal if we have only a bunch of controllers, but can we do better? I reckon we can.
Next step — AOP
We’ll use Spring’s AOP to write a pointcut expression that intercepts a controller method call, constructs a map of URL variables and their values to be checked. I like to think of this as an infrastructure-level component, that is decoupled from the actual business logic for preconditions via template method pattern:
We can place the precondition logic for companyId
and userId
into a dedicated Guardian component keeping it simple and focused:
Summary
We’ve looked into a problem where we needed to ensure that certain preconditions were met in order to continue with the main business logic. While sticking with conventional solutions (re-using repeated logic via inheritance — base controllers, or composition — dedicated components) works well, we have to remember to invoke it every time, but manual processes are not fail safe.
AOP allowed us to separate this concern completely, and as long as we stick to some basic conventions (having public controller methods, naming URL variables consistently) we’ve don’t need to worry about these preconditions anymore.
We have a handful of these Guardians in production at Help Scout today that make sure our URL variables are properly guarded, and undesirable requests are safely vetoed.
I’d love to hear your thoughts on this — leave a comment if you have ever faced a similar problem and how you solved it!
Code
You can find the sample code for this on Github: https://github.com/vrto/rest-guardian-aop
While this solution used Spring Boot, it is easy to adapt it to a different framework as well (since the Guardian code only uses AOP and reflection). During a recent project I’ve used it with Play! Framework for Java.