aboutsummaryrefslogtreecommitdiff
path: root/examples/defendpoint-examples.lisp
blob: a59d09d8b3ee079719df89662202a9bbc6688c20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
(defpackage #:weekend.examples.defendpoint
  (:use #:cl #:weekend)
  (:import-from #:flatbind #:do>))

(in-package :weekend.examples.defendpoint)

;;; The DICE ROLLER example, but this time with DEFENDPOINT:
(defparameter +digits+ "([0-9]+)")

(defendpoint roller
  :get :route "roll" (:rolls +digits+ parse-integer) "d" (:sides +digits+ parse-integer)
  :returns "text/plain"
  :parameters
  (sides integer "The number of sides the die being rolled has.")
  (rolls integer "The number of times to roll the die.")
  :documentation "Roll a SIDES-sided die ROLLS times, and announce the total."
  :handle (format nil "~ad~a = ~a"
                  rolls sides
                  (loop :repeat rolls :sum (1+ (random sides)))))


;;; EXAMPLE WITH MULTIPLE INTERACTING ENDPOINTS, AND A MIX-IN FOR
;;; AUTHENTICATION

;; Serves a form used to identify a user
(defendpoint who-are-you
  :get :route "who-are-you"
  :returns "text/html;charset=utf-8"
  :documentation "A form to identify yourself"
  :handle (with-output-to-string (*standard-output*)
            (princ "<html><head></head><body>")
            (princ "<form method='POST' action='/my-name-is'>")
            (princ "<input name='name' placeholder='Your Name'/>")
            (princ "<button type=submit>Go!</button>")
            (princ "</form></body></html>")))

;;; A mixin meant to grab the name from a cookie, used to authenticate
;;; all requests that need to have identified a user.
;;; If authentication fails, redirects to who-are-you.
(defclass identified ()
  ((name :accessor name :type string)))

(defmethod authenticate ((req identified))
  (or
   (do>
     name :when= (get-cookie "weekend-eg-name")
     :when (and (stringp name) (plusp (length name)))
     (setf (name req) name))
   (endpoint-redirect 'who-are-you)))


;;; Endpoint that extends IDENTIFIED and just greets the identified.
(defendpoint you-seem-to-be
  :using identified
  :get :route "you-seem-to-be"
  :returns "text/html;charset=utf-8"
  :documentation "Just says hello to an identified uesr"
  :handle (with-output-to-string (*standard-output*)
            (princ "<html><head></head><body>")
            (princ "<p>You seem to be ")
            (princ name) ; INHERITED FROM IDENTIFIED
            (princ ".</p></body></html>")))


;;; POST endpoint that handles setting the name cookie 
(defendpoint my-name-is
  :post :to "my-name-is"
  :parameters
  (name string "The name supplied by the user")
  :documentation "Set cookie for client's identity."
  :handle (progn
            (set-cookie "weekend-eg-name" :value name)
            (endpoint-redirect 'you-seem-to-be)))