Middleware stack

Reopening #150 against master.