Pedestal represents interceptors, its analog to Ring middleware, as data. Let’s look at how we can use that to conditionally inject a ClojureScript REPL into responses.
Two working definitions as we start
- Interceptor - a record containing keys corresponding functions for execution stages. Serves an analogous role to middleware in Ring.
- context - a map with all data relating to processing a request. Contains Ring request and response maps along with additional data.
Marking Routes with Metadata
We’ll start by adding metadata indicating that a browser REPL should be included in the response. We can either add it directly to an endpoint
or to an interceptor anywhere else in the chain
Interceptors serve a similar role as middlewares in Ring but the implementation is substantially different. See Pedestal’s docs for a full discussion, but for now the important difference is in how middlewares and interceptors are combined. In Ring, middlewares compose functionally
Pedestal represents interceptors sequentially, adding them as a queue to the request / response
:io.pedestal.impl.interceptor/queue). In broad strokes, requests are processed by taking an interceptor from the queue and applying its
:enter function to the
context, producing a new
context that the next interceptor in the queue will act on. As each interceptor is visited, it’s added to a stack in the
context that will be traversed on the
:leave stage. The code is well worth a read.
Knowing that the other interceptors involved in processing a request are visible in the context’s
:io.pedestal.impl.interceptor/queue, we can write an interceptor that scans the queue looking for the
:browser-repl metadata and injects a repl into the response if it’s found
around to implement
browser-repl so that we can examine the interceptor queue in the
before stage and set a flag in the
:include-browser-repl that we’ll read when a response is present in the
leave phase and decide whether to call
inject-repl is a function that handles the mechanics of modifying the response, along the lines of
Note Brian Rowe and Alex Redington suggested a couple of very nice extensions to this idea that I’d recommend studying before implementing it.
Kinda cool, right? Interceptors are data, and neat approaches fall out. We use a similar pattern for authorization.
Also, big thanks to Brian Rowe and Rick Hall for a number of improvements to this post!