# Unfiltered: A Scala HTTP Toolkit Built on Netty and Servlet Filters

> Unfiltered is a Scala library for composing HTTP request handlers using either the Java Servlet API or Netty, split into focused modules that you pull in as needed. It offers request extractors and response combinators without bundling a router, template engine, or authentication layer.

**unfiltered/unfiltered** — A toolkit for servicing HTTP requests in Scala. websockets A minimal server websocket interface build on netty Community Join the Unfiltered mailing list on Google Groups.

- Repository: https://github.com/unfiltered/unfiltered
- Website: http://unfiltered.ws
- Stars: 711 · Forks: 111
- Language: Scala
- License: MIT
- Published: 2026-09-07 · Updated: 2026-09-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/unfiltered-unfiltered

## A Minimal Contract for HTTP in Scala

Unfiltered addresses a specific gap in the Scala server ecosystem: how to handle HTTP requests without committing to a full application framework. The library's two foundational concepts are request extractors and response combinators. An extractor pattern-matches against an incoming request to pull out headers, parameters, or the HTTP method. A response combinator assembles the outgoing response from discrete parts. These two primitives are defined in the core library module, independent of any transport, which means either the servlet or Netty backend can run the same core logic.

The intended audience is Scala developers who want to host an HTTP service in an existing JVM application, or who want to choose their own abstractions for routing and views rather than adopting a framework's opinion on those subjects. It suits projects where the HTTP layer needs to be thin, testable, and easy to swap out when requirements change.

## Twelve Modules, Each With One Job

The repository is organized into twelve independent modules. The library module defines the core types: request extractors and response combinators that the rest of the codebase builds on. From there, two paths diverge.

The servlet path includes filter, which binds extractors and combinators to the Java Servlet API, filter-async for asynchronous servlet handling, jetty for an embedded Jetty server that runs servlet filters without an external container, and uploads for multipart form data using the Servlet API.

The Netty path includes netty, which binds the library to a Netty channel handler and provides its own embedded server, netty-uploads for multipart posts over Netty, and netty-websockets for a minimal WebSocket interface. The json4s module adds extractors for JSONP and JSON request bodies and works across both paths.

For testing, specs2 provides helpers for testing Intents with the specs2 specification library, and a scalatest module appears in the repository tree alongside it.

## Servlet Filters vs. Netty: Choosing a Backend

Choosing between the servlet-based and Netty-based modules is the first architectural decision when setting up Unfiltered. The servlet path integrates with any Servlet 3.x container and works well when the application is already deployed behind a managed server such as Tomcat or WildFly. The jetty module offers an embedded option on the same path, useful for self-contained deployments or unit tests that spin up a real server in process.

The Netty path bypasses the servlet specification entirely. It gives direct control over the Netty channel pipeline and is the only path that supports WebSockets through the netty-websockets module. Netty's threading model is event-loop based, which differs from the servlet thread-per-request model; applications that rely on thread-local state in servlet filters will need changes before moving to Netty.

The two paths do not mix: a handler written for the servlet filter module does not run on the Netty server without modification.

## WebSocket Support Through the Netty Module

The netty-websockets module provides a minimal server-side WebSocket interface layered on Netty. The README describes it as a minimal server websocket interface built on netty, which signals that the abstraction is intentionally thin rather than a batteries-included framework. A giter8 template for scaffolding a WebSocket-based chat application is hosted at unfiltered-websockets.g8 in the unfiltered organization on GitHub.

Because WebSocket support depends on Netty, it is unavailable when running on the servlet path. Applications that need WebSocket connections must use the Netty backend. The README does not document specifics of the handshake lifecycle, subprotocol negotiation, or connection close handling. Teams relying on those details would need to check the netty-websockets source directly or consult the documentation at unfiltered.ws.

## JSON and Multipart Request Handling

The json4s module adds extractors for JSONP callbacks and JSON request bodies, bridging Unfiltered's extraction model with the json4s library. It allows request handlers to pattern-match directly on parsed JSON values without writing custom parsing code in each handler.

Multipart support is split between two modules. The uploads module handles multipart forms via the Servlet API, and netty-uploads handles the same over Netty. Each depends on its respective backend, so adding multipart support means pulling the matching module for whichever execution path the application uses. The README gives no detail about maximum file size limits or streaming behavior for large uploads. Teams moving large files would want to verify the specific behavior at unfiltered.ws before deploying to production.

## Where Unfiltered Is the Wrong Tool

Unfiltered does not include routing. The library provides extractors for matching on HTTP methods, paths, and parameters individually, but the developer writes the composition logic that dispatches a request to the right handler. In practice this means writing pattern-match branches manually. For an application with dozens of endpoints, the absence of a declarative router becomes significant work.

There is no middleware concept, no dependency injection integration, no session management, and no templating. Each of those concerns requires a separate library choice. The thin layer approach suits developers who want that control, but it is a real cost for teams that want a working API scaffold quickly.

The library has no documented support for HTTP/2 or HTTP/3. The README itself contains no usage examples beyond pointing to unfiltered.ws and the giter8 templates.

## Maintenance Status, Licensing, and a Functional Alternative

The repository last received a push on 2026-09-25 and is not archived, indicating ongoing maintenance. The project is released under the MIT license, which permits use, modification, and redistribution without restrictions beyond attribution.

A comparable library in the Scala HTTP space is http4s, which takes a purely functional approach using the cats-effect IO monad rather than Unfiltered's extraction and combinator model. http4s provides its own router and integrates with the Typelevel ecosystem of libraries. Teams already working in the cats-effect style would find http4s more consistent with their existing code. Unfiltered suits developers who prefer to stay closer to the JVM's existing servlet and Netty infrastructure without adopting a new effect system.

Giter8 templates for starting a new Netty server project, a WAR deployment, a WebSocket application, or a basic embedded server are hosted in the unfiltered organization on GitHub.

## Conclusion

Unfiltered suits Scala developers who want a thin binding over Netty or Servlet filters without committing to a framework's routing or templating opinions. It is not a good fit for teams who need HTTP/2, a built-in router, or a ready-made application scaffold. Before adopting it, check the documentation at unfiltered.ws for current module compatibility with your version of Scala and your target runtime.

## FAQ

### Does Unfiltered include a router for dispatching requests to multiple handlers?

The README does not document a built-in router. Unfiltered's core library provides request extractors and response combinators, and the developer composes the dispatch logic using Scala pattern matching across those extractors.

### Can Unfiltered run without an external web server?

Yes. The jetty module provides an embedded Jetty server for running servlet filters without an external container, and the netty module provides an embedded Netty server that can be started directly from application code.

### Where is the official documentation for Unfiltered?

The README points to unfiltered.ws as the main documentation site. The repository also links to giter8 templates for common project layouts, including Netty server, WAR deployment, and WebSocket applications.

## Sources

- [Official documentation](http://unfiltered.ws)
- [Official README](https://github.com/unfiltered/unfiltered#readme)
- [Project repository](https://github.com/unfiltered/unfiltered)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/unfiltered-unfiltered
