Help Scout Engineering & Product

How we craft

Follow publication

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 system
  • userId exists within the system
  • userId belongs to the company with companyId

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.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Written by vrto

Software Engineer with focus on Java stack. Clean Coder, TDD practitioner. Currently working with great folks at HelpScout.

No responses yet

Write a response