Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Route Handlers

Each endpoint is an async function that returns a Response.

JSON Response Helper

(bind cors-headers (obj
  :access-control-allow-origin "*"
  :access-control-allow-methods "GET, POST, OPTIONS"
  :access-control-allow-headers "Content-Type"))

(func json-response
  :args (:any data :number status)
  :returns :any
  :body
  (bind headers (new Headers))
  (headers:set "Content-Type" "application/json")
  (headers:set "Access-Control-Allow-Origin" "*")
  (new Response (JSON:stringify data) (obj :status status :headers headers)))

Shorten Handler

(export (async (func handle-shorten
  :args (:any request)
  :body
  (try
    (bind body (await (request:json)))
    (if (= body:url undefined)
      (json-response (obj :error "url required") 400)
      (do
        (bind code (await (generate-unique-code)))
        (bind entry (Entry code body:url (Date:now) 0))
        (await (save-entry entry))
        (json-response
          (obj :code code :short-url (template "http://localhost:8080/" code)) 200)))
    (catch e
      (json-response (obj :error e:message) 400))))))

Redirect Handler

(export (async (func handle-redirect
  :args (:string code)
  :body
  (bind entry (await (get-entry code)))
  (if (= entry null)
    (new Response "Not Found" (obj :status 404))
    (do
      (await (increment-clicks code))
      (match entry
        ((Entry c url ca clicks)
         (bind headers (new Headers))
         (headers:set "Location" url)
         (new Response null (obj :status 302 :headers headers)))))))))

Each handler takes typed inputs, returns a Promise of Response, uses match on type variants, and returns appropriate HTTP status codes.