A Scala library for servlet filters
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 53 commits ahead, 1412 commits behind unfiltered:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Unfiltered embraces the HTTP protocol, Scala, type-safety, and minimalism. It enables applications to handle HTTP requests as partial functions that take requests and return functions to respond to them. Typically, applications pattern-match requests against nested extractor objects. HTTP responses are defined with response combinator functions.

The request response cycle reduces to a pattern matching clause similar to message handling in the Scala actors library.

object Server {
  def main(args: Array[String]) {
    unfiltered.jetty.Http(8080).filter(unfiltered.filter.Planify {
      case _ => Ok ~> ResponseString("Hello there")

The above example starts an embedded web server at http://localhost:8080 and responds to all requests with a "Hello there" message. It runs as a standalone Java application. You can also define filter classes, to be added by configuration to a servlet container like Tomcat or Google App Engine.


Intents are the core library's interface for handling requests and responses. Specifically:

type Intent[T] = PartialFunction[HttpRequest[T], ResponseFunction]

Intent functions pattern match against incoming requests and return a function that produces the desired response. Type parameters allow the client or extension library to directly access the underlying requests and response objects though the underlying method of HttpRequest and HttpResponse.


Plans assign an Intent to particular request and response bindings. For example, the trait unfiltered.filter.Plan defines a javax.servlet.Filter that delegates to itsintent method. The class unfiltered.netty.cycle.Plan defines a channel handler similarly. A future Plan trait might define a Servlet. Plan is a convention (and not currently a common interface) to apply an Intent to any request handling framework.

Request Extractors

A request extractor is an extractor that accepts an HTTP request and returns a tuple of something useful along with the request to chain other extractors with.

An example signature would might be

def unapply(x: HttpServletRequest): (Y, HttpServletRequest)

Unfiltered provides a library of extractors for matching common most HTTP requests attributes.

At the most basic level...

GET, POST, PUT, DELETE, HEAD // match request methods

Path // matches request uris

Seg // matches request path elements

You can compose your own patterns using these and other extractors:

PUT(Path(Seg("a" :: b :: "c" :: d :: Nil), SomeOtherExactor(foo, request)))

Response Combinators

A response combinator is a function that takes a another function as its argument. Using these combinators, applications compose a function that acts on the Java servlet primitives to respond to the request. In general, applications employ these built-in combinators to act on primitives rather than referencing them directly, but they are free to construct responses ad hoc if necessary.

type ResponseFunction = HttpServletRequest => HttpServletRequest

Core response functions are implemented as responders which can be chained together with ~>.

These response functions are the expected return values of Intents.

A restful api for a given resource might look something like

unfiltered.filter.Planify {
  case GET(Path(Seg("resource" :: id :: Nil), r)) => Store(id) match {
    case Some(resource) => ResponseString(render(resource).as(r match {
      case Accepts.Json(_) => 'json
      case Accepts.Xml(_) => 'xml
      case _ => 'html
    }) ~> Ok 
    case _ => NotFound
  case POST(Path(Seg("resource" :: id :: Nil), Bytes(body, r))) => Store(id, body) match {
    case Some(id) => ResponseString(render("resource created").as(r match {
      case Accepts.Json(_) => 'json
      case Accepts.Xml(_) => 'xml
      case _ => 'html
    }) ~> Created
    case _ => BadRequest
  case PUT(Path(Seg("resource" :: id :: Nil), Bytes(body, r))) => Store(id, body) match {
    case Some(id) => ResponseString(render("resource updated").as(r match {
      case Accepts.Json(_) => 'json
      case Accepts.Xml(_) => 'xml
      case _ => 'html
    }) ~> Ok
    case _ => BadRequest
  case DELETE(Path(Seg("resource" :: id :: Nil),_)) => Store.delete(id) match {
    case Some(id) => Ok
    case _ => Gone



The core application library for Unfiltered. This module provides interfaces and implementations of core request extractors and response combinators.


Binds the core library to filters in the servlet 2.3 API.


Provides an embedded web server abstraction for serving filters.


An embedded server that adheres to the ajp protocol.


Binds the core library to a Netty channel handler and provides an embedded server.


Provides helpers for testing Intents with specs.


Provides extractors for multipart posts using the servlet API.


Provides extractors for working with jsonp and transforming json request bodies.


Scalate template support.


A minimal server websocket interface build on netty


Unfiltered is a cross built project, currently for the following Scala versions

2.7.7, 2.8.0, 2.8.1

via sbt

For standalone projects, you'll want unfiltered-jetty as well as a binding module:

import sbt._
class Project(info:ProjectInfo) extends DefaultProject(info) {
  val ufj = "net.databinder" %% "unfiltered-jetty" % "0.3.0"
  val uff = "net.databinder" %% "unfiltered-filter" % "0.3.0"

To specify individual modules, specify the module name in the dependency.

import sbt._
class Project(info:ProjectInfo) extends DefaultProject(info) {
  val ufx = "net.databinder" %% "unfiltered-{module}" % "0.3.0"

See the template application for an example of a basic Unfiltered application.


Join the Unfiltered mailing list on Nabble.


overly complex extractors

If you design your partial functions in such a way that they become overly complex you might run into the following exception

Exception in thread "main" java.lang.Error: ch.epfl.lamp.fjbg.JCode$OffsetTooBigException: offset to
o big to fit in 16 bits

This is an open ticket the the Scala library but this is not really a limitation of Scala so much as the jvm.

As paulp put it

Yes. Like it says in the ticket, exponential space. It is not the compiler which is angry, it is the jvm, which sets a hard limit on the size of a method. The compiler's emotional state at that moment would be better characterized as pollyanna-esque.

The work around is good software design. Break up your problems into parts and put them in separate filters. Don't give one Plan too much responsibility.