Rack Middleware

Middleware is a very powerful tool that is usually used to filter incoming requests or outgoing responses to your web application, and solves some problems in a very elegant and DRY way. It is usually a pluggable component acting as a filter in the request/response flow. Has the benefit of being easy to reuse in any application that needs them.

WSGI is an interface, that defines how web applications and web servers talk to each other. WSGI is the name most used with connection to the Python programming language, but WSGI has equivalents in most other programming languages used to create web application. For example Rack is the equivalent of WSGI for the Ruby programming language. Although it might not be apparent, WSGI in Python and Rack in Ruby are almost identical with regards to how you create middleware for them.

Popular web frameworks usually have their own way of adding middleware to WSGI/Rack that is sometimes simpler. One such example is the Django web framework that has a really excellent and simple way of adding middleware to your application, described in the Django middleware documentation.

In Rack (and in Python’s WSGI) middleware usually looks like this:
https://gist.github.com/2872916.js?file=some_rack_middleware.rb

Django makes it simpler by adding methods for each step in the filter:
https://gist.github.com/2872916.js?file=some_django_middleware.py

The best part about Rack middleware, is the excellent way to test your custom middleware using Rack::Test. It took a bit of wrapping my head around it, but when I finally had the eureka moment it all snapped into place. Let me demonstrate with a simple example that shows how to test a Rack middleware using RSpec and Rack::Test.

https://gist.github.com/2872916.js?file=rack_test_middleware.rb

The secret sauce is including Rack::Test::Methods at the start of the description, and it does all the magic of using “app” and allowing to get/post/etc… as documented in the Rack::Test::Methods documentation.

Hope this helps someone, leave your comments and/or questions below.