A tiny routing library for Common Lisp targeting Clack.
0.1IntroductionTINY-ROUTES is a bare-bones routing library for Common Lisptargeting the Clack web application development. Its only externaldependency is CL-PPCRE which is used to match and bind dynamic URLparameters.
0.2PrerequisitesThe following lists the prerequisites needed to follow thisREADME successfully.
- Common Lisp web frameworks
- Specifically, you should be familiar with HTTP methods.
0.3MotivationClack's killer feature is that it allows us server-agnostic webapplication. Namely, web applications that are not tied to aspecific server library such as Hunchentoot, Toot, or Wookie.
Clack distills a web application down to just a
that accepts a
request (or an
environment) object (i.e., a
plist containing data like HTTP request method, request URI, among
others) and returns an appropriate HTTP response. This HTTP
response is represented simply by a list of three elements
containing the HTTP status code, HTTP headers, and a response body.
This simplification provides developers with a great amount of
flexibility given that we can leverage the entire power of lisp to
create these simple list structures representing HTTP responses.
However, I quickly found that Clack' itself does not offer tools or
guidance on how such request
handler functions should be written,
composed, and ultimately managed.
The purpose of TINY-ROUTES is to provide a small set of helper/utility functions and macros to aid the developer in building clack applications by breaking them up into composable request handlers and middleware functions.
0.4DefinitionsThe following represents definitions used in this document.
- A plist representing an HTTPrequest. Please see Clack for a list of supported fields.Finally, please note that users and/or middleware are allowed(and encouraged!) to add new fields to the request object for newfunctionality.
- A list or lambda representing an HTTP response. Perthe Clack documentation, a response can either be:
- A list of three elements representing an HTTP status code,HTTP headers, and a response body
- A lambda accepting a
responsefunction to be called with a
- A function that accepts a
requestand returns a
- A combinator function that accepts a handler asits first argument, optionally accepts other arguments, andreturns a potentially different handler.
0.5UsageThe following application exposes:
- A static endpoint which returns an HTTP 200 response with the body
- A dynamic endpoint which returns an HTTP 200 response with astring containing the bound value =account-
- A catch-all handler which returns an HTTP 404 response with thebody
Each line in the example is detailed below
(define-routes *app* ; (1) (define-get "/" () ; (2) (ok "alive")) ; (3) (define-get "/accounts/:account-id" (request) ; (4) (let ((account-id (path-parameter request :account-id))) ; (5) (ok (format nil "Your account id: ~a." account-id)))) ; (6) (define-any "*" () ; (7) (not-found "not-found"))) ; (8)
define-routesmacro accepts a variable number of handlersand returns a new handler that loops through each handler andreturns the first non-nil response it finds.
define-getmacro creates a handler that matches on HTTP GETrequests. The macro accepts a
path-templateand a requestbinding. Please note TINY-ROUTES also exposes similar macros forPOST, PUT, HEADER, HEAD, and OPTIONS.
okfunction accepts an optional body and returns aresponse list with HTTP status 200 OK.
define-getmacro now receives a path-template with adynamic parameter named
:account-id. This value associatedwith this dynamic parameter is made available as part of therequest's path-params as seen in line (5).
path-paramselector function can be used to quickly parsea path param from a request object.
- We leverage the
formatfunction to show that the response bodycan also be dynamic.
define-anymacro can be used to implement catch allroutes.
not-foundfunction accepts an optional body and returns aresponse list with HTTP status 404 Not Found.
0.6InstallationTo install via quicklisp please run the following in your running REPL:
0.7Sample codePlease see tiny-routes-realworld-example-app for a full-fledgedClack REST application demonstrating one possible use oftiny-routes.