A tiny routing library for Common Lisp targeting Clack.

Upstream URL



Johnny Ruiz <johnny@ruiz-usa.com>


BSD 3-Clause


TINY-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.


The following lists the prerequisites needed to follow thisREADME successfully.
  1. Common Lisp web frameworks
  2. HTTP
  3. Quicklisp


Clack'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 handler function 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.


The following represents definitions used in this document.
request or environemnt
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:
  1. A list of three elements representing an HTTP status code,HTTP headers, and a response body
  2. A lambda accepting a response function to be called with aresponse asynchronously.
A function that accepts a request and returns aresponse or nil.
A combinator function that accepts a handler asits first argument, optionally accepts other arguments, andreturns a potentially different handler.


The following application exposes:
  • A static endpoint which returns an HTTP 200 response with the bodyalive
  • 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 not-found.
(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)
Each line in the example is detailed below
  1. The define-routes macro accepts a variable number of handlersand returns a new handler that loops through each handler andreturns the first non-nil response it finds.
  2. The define-get macro creates a handler that matches on HTTP GETrequests. The macro accepts a path-template and a requestbinding. Please note TINY-ROUTES also exposes similar macros forPOST, PUT, HEADER, HEAD, and OPTIONS.
  3. The ok function accepts an optional body and returns aresponse list with HTTP status 200 OK.
  4. The define-get macro 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).
  5. The path-param selector function can be used to quickly parsea path param from a request object.
  6. We leverage the format function to show that the response bodycan also be dynamic.
  7. The define-any macro can be used to implement catch allroutes.
  8. The not-found function accepts an optional body and returns aresponse list with HTTP status 404 Not Found.


To install via quicklisp please run the following in your running REPL:
(ql:quickload "tiny-routes")

0.7Sample code

Please see tiny-routes-realworld-example-app for a full-fledgedClack REST application demonstrating one possible use oftiny-routes.


Dependencies (4)

  • cl-cookie
  • cl-ppcre
  • fiveam
  • uiop

Dependents (0)

    • GitHub
    • Quicklisp