Our thoughts, knowledge, insights and opinions

Request rate limiting in Lift

A few weeks ago I’ve started coding in a big Lift project. One of my first tasks was to create a simple HTTP API for communication with underlying Akka actors. This one was easy thanks to RestHelper.

Second task was to add request rate limiting for this API. It appears that Lift despite its many features doesn’t have rate limiting plugin. So, I had to roll my own.

Overview

General idea of how rate limits should be implemented was taken from GitHub API. You can check status of a rate limit in HTTP headers of each response:

Rate limit not reached:

jan@navicon ~> curl -i http://127.0.0.1:3457/hello
HTTP/1.1 200 OK
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
X-RateLimit-Reset: 1390484684129

Rate limit reached:

jan@navicon ~> curl -i http://127.0.0.1:3457/hello
HTTP/1.1 403 Forbidden
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1390484708009

{
  "message":"API rate limit exceeded."
}

Code

Whole example can be found in my gist.

Usage

Just wrap your handler functions with withRateLimit. Note that you can choose which parts of your API have rate limits enabled.

class RestHelperWithRateLimit extends RestHelper with RateLimit {
 
  val rateLimitConfig: RateLimit.Config = RateLimit.Enabled(100, 1 minute)
 
  serve {
    withRateLimit {
      case "hello_limits" :: Nil => OkResponse
    }
  }
  
  serve {
    case "no_limits" :: Nil => OkResponse
  }
 
}

Error response

We had a discussion whether HTTP error response code should be 403 Forbidden or 429 Too Many Requests as RFC 6585 suggests. I was the coder so I chose 403. If you don’t like it just override RateLimit.errorHandler method in your RestHelper:

  override def errorHandler(req: Req, 
                            config: RateLimit.Enabled, nextReset: Long): () => Box[LiftResponse] = {
    PlainTextResponse("", Nil, 429)
  }

Last but not least, this example compiles with Lift 2.6-M2.

You like this post? Want to stay updated? Follow us on Twitter or subscribe to our Feed.

by Jan Ziniewicz
January 23, 2014
Tags : Scala Lift REST