|
See the guide
This is the detailed interceptor reference; if you are new to Pedestal
you may want to start with the guides:what-is-an-interceptor.adoc.
|
Interceptors are the basic unit of work in Pedestal. The
core library provides interceptors that are generally useful for
creating HTTP web services. Applications augment those with their own
logic to handle.
An interceptor is a pair of unary functions
An interceptor must provide at least one of :enter, :leave and :error.
Each function is called with a context-map.adoc and must return either a context
map or a {core_async} channel that will deliver a context map; the latter case triggers
asynchronous request processing.
Pedestal calls the :enter function on the way "in" to handling a
request. It calls the :leave function on the way back "out". This is
shown here for a single interceptor:
seqdiag {
"Interceptor Chain" -> Interceptor [label=":enter"]
"Interceptor Chain" <- Interceptor
"Interceptor Chain" -> "Other Interceptors"
"Interceptor Chain" <- "Other Interceptors"
"Interceptor Chain" -> Interceptor [label=":leave"]
"Interceptor Chain" <- Interceptor
}
Either the :enter or :leave function may be omitted without harm.
Logically speaking, interceptors form a queue.
During the :enter phase, the next interceptor is popped off the queue,
pushed onto the leave stack, and its :enter function, if any, is executed.
Once the handler (or other interceptor) adds a :response to the context,
the chain logic switches to :leave mode: it pops interceptors off
the leave stack and invokes the :leave function, if any.
Because it’s the leave stack the :leave functions are invoked
in the opposite order from the :enter functions.
seqdiag {
"Interceptor Chain" -> A [label=":enter"]
"Interceptor Chain" <- A
"Interceptor Chain" -> B [label=":enter"]
"Interceptor Chain" <- B
"Interceptor Chain" -> C [label=":enter"]
"Interceptor Chain" <- C
"Interceptor Chain" -> C [label=":leave"]
"Interceptor Chain" <- C
"Interceptor Chain" -> B [label=":leave"]
"Interceptor Chain" <- B
"Interceptor Chain" -> A [label=":leave"]
"Interceptor Chain" <- A
}
Both the queue and the stack reside in the context map. Since
interceptors can modify the context map, that means they can change
the plan of execution for the rest of the request! Interceptors are
allowed to enqueue more interceptors to be called, or they can
terminate the request.
This process, of running all the interceptor :enter functions, then running
the interceptor :leave functions, is called executing the interceptor chain.