Pedestal is data driven, and the routing information starts in one form (as data) and is then
transformed in a couple of stages to reach a final result that can be used to route incoming requests.
The start is the route specification.
Pedestal has three built-in formats for route specification:
table, terse, and verbose. Table is the newest format (but still old - it dates back to 2016)
and is the preferred format; the others are maintained for compatibility.
For each of the built-in formats, there is a function that can convert that specific format
into a routing table (also known as expanded routes). Pedestal can often figure out which
function to invoke based on the kind of data: set, vector, or map:
flowchart
subgraph ExpandableRoutes/-expand-routes
table("#{} table")-->|table/table-routes|expanded
terse("[] terse")-->|terse/terse-routes|expanded
map("{} verbose")-->|terse/map-routes->vec-routes|expanded
end
expanded(expanded routes)-->|RouterSpecification/router-spec|inter
cons(Router Constructor)-->inter
inter(Routing Interceptor)
Route specifications are the data values that spell out the possible routes.
These are normalized and expanded into a routing table.
A Router Constructor function is provided with the routing table, and applies a specific strategy to match incoming requests
to the provided routes; there are a few different constructor functions, each
with different limitations and trade-offs.
The constructor returns a
api:Router[ns=io.pedestal.http.route.router] instance encapsulating the routing table and the
strategy.
The routing interceptor builds on a Router
to dispatch incoming requests to routes
defined by the route specification. It identifies the route matching the incoming request
and queues up route-specific interceptors to handle the request.
Generally, all of this is automatic; an application provides a route specification in the :io.pedestal.http/route key
of the service-map.adoc (and perhaps a value for :io.pedestal.http/router) and a routing
interceptor is automatically created.