git.fiddlerwoaroof.com
Browse code

documentation: continue working on the documentation

Ed Langley authored on 30/08/2019 07:00:12
Showing 4 changed files
... ...
@@ -71,6 +71,11 @@
71 71
 
72 72
    #+NAME: new-todo
73 73
    #+BEGIN_SRC lisp :tangle no
74
+     (defvar *external-host*
75
+       "localhost")
76
+     (defvar *external-port*
77
+       5000)
78
+
74 79
      (defun new-todo (value)
75 80
        (let ((id (next-id)))
76 81
          (setf (todo id)
... ...
@@ -78,7 +83,7 @@
78 83
                 (rutilsx.threading:->>
79 84
                  value
80 85
                  (acons "completed" 'yason:false)
81
-                 (acons "url" (format nil "http://localhost:5000/todo/~d" id)))
86
+                 (acons "url" (format nil "http://~a:~d/todo/~d" *external-host* *external-port* id)))
82 87
                 :test 'equal))))
83 88
    #+END_SRC
84 89
 
... ...
@@ -118,6 +123,62 @@
118 123
    :               "title": "write-better-documentation",
119 124
    :               "completed": YASON:FALSE>)
120 125
   
126
+   
127
+* Routing
128
+
129
+** Routing utilities
130
+
131
+   The core utility here is the =defroutes= macro.  This takes a
132
+   sequence of endpoint descriptions which contain nested definitions
133
+   for HTTP verbs and expands to ningle's functions for manipulating
134
+   routes.
135
+   
136
+   #+BEGIN_SRC lisp :exports both :tangle no :results verbatim
137
+     (macroexpand-1
138
+      '(defroutes app
139
+        ("/"
140
+         (:GET (handler () (todos)))
141
+         (:POST (handler (v) (new-todo v)))
142
+         (:DELETE (handler () (clear-todos))))))
143
+   #+END_SRC
144
+
145
+   #+RESULTS:
146
+   #+begin_example
147
+   (LET ((#:APP1852 APP))
148
+     (SETF (NINGLE/APP:ROUTE #:APP1852 "/" :METHOD METHOD)
149
+             (HANDLER NIL
150
+               (TODOS))
151
+           (NINGLE/APP:ROUTE #:APP1852 "/" :METHOD METHOD)
152
+             (HANDLER (V)
153
+               (NEW-TODO V))
154
+           (NINGLE/APP:ROUTE #:APP1852 "/" :METHOD METHOD)
155
+             (HANDLER NIL
156
+               (CLEAR-TODOS))))
157
+   T
158
+   #+end_example
159
+
160
+   #+NAME: routing-helpers
161
+   #+BEGIN_SRC lisp
162
+     (defmacro defroutes (app &body routes)
163
+       (alexandria:once-only (app)
164
+         `(setf
165
+           ,@(loop for (target . descriptors) in routes
166
+                   append (loop for (method callback) in descriptors
167
+                                append `((ningle:route ,app ,target
168
+                                                       :method method)
169
+                                         ,callback))))))
170
+
171
+     (defun success (value)
172
+       (list 200 nil value))
173
+
174
+     (defmacro handler ((&optional (sym (gensym "PARAMS"))) &body body)
175
+       `(lambda (,sym)
176
+          (declare (ignorable ,sym))
177
+          (success
178
+           (fwoar.lack.json.middleware:wrap-result
179
+            (progn ,@body)))))
180
+   #+end_SRC
181
+
121 182
 * Source
122 183
 ** model.lisp source code
123 184
 
... ...
@@ -142,44 +203,27 @@
142 203
 
143 204
 ** routing.lisp source 
144 205
 
145
-   #+BEGIN_SRC lisp :tangle routing.lisp :noweb yes
146
-   <<package-include>>
147
-   (defmacro defroutes (app &body routes)
148
-     "Define a set of routes for given paths. the ROUTES parameter expects this format:
149
-      ((\"/path/to/{route}\" :method :POST) route-callback) the AS-ROUTE macro helps one
150
-      avoid binding function values to the route for flexibility."
151
-     (alexandria:once-only (app)
152
-       `(progn
153
-          ,@(loop for ((target &key method) callback) in routes
154
-                  collect `(setf (ningle:route ,app ,target :method ,(or method :GET)) ,callback)))))
155
-
156
-
157
-   ;; routing
158
-   (defun success (value)
159
-     (list 200 nil value))
160
-
161
-   (defmacro handler ((&optional (sym (gensym "PARAMS"))) &body body)
162
-     `(lambda (,sym)
163
-        (declare (ignorable ,sym))
164
-        (success
165
-         (fwoar.lack.json.middleware:wrap-result
166
-          (progn ,@body)))))
167
-
168
-   (defun get-id (params)
169
-     (parse-integer (serapeum:assocdr :id params)))
170
-
171
-   (defun setup-routes (app)
172
-     (defroutes app
173
-       (("/" :method :GET)            (handler () (todos)))
174
-       (("/" :method :POST)           (handler (v) (new-todo v)))
175
-       (("/" :method :DELETE)         (handler () (clear-todos)))
176
-       (("/todo/:id" :method :GET)    (handler (v) (todo (get-id v))))
177
-       (("/todo/:id" :method :DELETE) (handler (v)
178
-                                        (delete-todo (get-id v))
179
-                                        nil))
180
-       (("/todo/:id" :method :PATCH)  (handler (v)
181
-                                        (update-todo (get-id v) 
182
-                                                     (remove :id v :key #'car))))))
206
+   #+BEGIN_SRC lisp :tangle routing.lisp :noweb yes :comments noweb 
207
+     <<package-include>>
208
+
209
+     <<routing-helpers>>
210
+
211
+     ;; routing
212
+     (defun get-id (params)
213
+       (parse-integer (serapeum:assocdr :id params)))
214
+
215
+     (defun setup-routes (app)
216
+       (defroutes app
217
+         ("/" (:GET (handler () (todos)))
218
+              (:POST (handler (v) (new-todo v)))
219
+              (:DELETE (handler () (clear-todos))))
220
+         ("/todo/:id" (:GET    (handler (v) (todo (get-id v))))
221
+                      (:DELETE (handler (v)
222
+                                 (delete-todo (get-id v))
223
+                                 nil))
224
+                      (:PATCH  (handler (v)
225
+                                 (update-todo (get-id v) 
226
+                                              (remove :id v :key #'car)))))))
183 227
    #+END_SRC
184 228
 
185 229
 ** main.lisp source 
... ...
@@ -3,7 +3,7 @@
3 3
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4 4
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
5 5
 <head>
6
-<!-- 2019-08-29 Thu 13:51 -->
6
+<!-- 2019-08-30 Fri 02:00 -->
7 7
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 8
 <meta name="viewport" content="width=device-width, initial-scale=1" />
9 9
 <title>TODO backend implementation using CL and fukamachi/ningle</title>
... ...
@@ -285,28 +285,33 @@ for the JavaScript code in this tag.
285 285
 <h2>Table of Contents</h2>
286 286
 <div id="text-table-of-contents">
287 287
 <ul>
288
-<li><a href="#org4335b3f">1. Setup</a></li>
289
-<li><a href="#orgd9badd7">2. todo API</a>
288
+<li><a href="#orgf719c2d">1. Setup</a></li>
289
+<li><a href="#org5024541">2. todo API</a>
290 290
 <ul>
291
-<li><a href="#org28e1af7">2.1. List-level APIs</a></li>
292
-<li><a href="#orgdb74c86">2.2. Getting/Replacing a todo</a></li>
293
-<li><a href="#org0c6b1ff">2.3. Adding and modifying todos</a></li>
294
-<li><a href="#org3a3c9b0">2.4. Examples</a></li>
291
+<li><a href="#org066a36a">2.1. List-level APIs</a></li>
292
+<li><a href="#org8f0d41e">2.2. Getting/Replacing a todo</a></li>
293
+<li><a href="#org5e267ef">2.3. Adding and modifying todos</a></li>
294
+<li><a href="#org856ed57">2.4. Examples</a></li>
295 295
 </ul>
296 296
 </li>
297
-<li><a href="#orgec2861c">3. Source</a>
297
+<li><a href="#org8f02b65">3. Routing</a>
298 298
 <ul>
299
-<li><a href="#org98cfbdd">3.1. model.lisp source code</a></li>
300
-<li><a href="#orgd68289a">3.2. routing.lisp source</a></li>
301
-<li><a href="#org54c59b7">3.3. main.lisp source</a></li>
299
+<li><a href="#org93dcda5">3.1. Routing utilities</a></li>
300
+</ul>
301
+</li>
302
+<li><a href="#orgdec30ec">4. Source</a>
303
+<ul>
304
+<li><a href="#org1cf20cf">4.1. model.lisp source code</a></li>
305
+<li><a href="#orgbce9205">4.2. routing.lisp source</a></li>
306
+<li><a href="#orgc91e7f6">4.3. main.lisp source</a></li>
302 307
 </ul>
303 308
 </li>
304 309
 </ul>
305 310
 </div>
306 311
 </div>
307 312
 
308
-<div id="outline-container-org4335b3f" class="outline-2">
309
-<h2 id="org4335b3f"><span class="section-number-2">1</span> Setup</h2>
313
+<div id="outline-container-orgf719c2d" class="outline-2">
314
+<h2 id="orgf719c2d"><span class="section-number-2">1</span> Setup</h2>
310 315
 <div class="outline-text-2" id="text-1">
311 316
 <ul class="org-ul">
312 317
 <li><code class="src src-sh">git clone https://github.com/fiddlerwoaroof/data-lens.git ~/quicklisp/local-projects/data-lens</code></li>
... ...
@@ -326,8 +331,8 @@ After this, all the tests <a href="http://www.todobackend.com/specs/index.html?h
326 331
 </div>
327 332
 </div>
328 333
 
329
-<div id="outline-container-orgd9badd7" class="outline-2">
330
-<h2 id="orgd9badd7"><span class="section-number-2">2</span> todo API</h2>
334
+<div id="outline-container-org5024541" class="outline-2">
335
+<h2 id="org5024541"><span class="section-number-2">2</span> todo API</h2>
331 336
 <div class="outline-text-2" id="text-2">
332 337
 <p>
333 338
 We use a fairly simple structure for our "database": a fset map (a
... ...
@@ -337,8 +342,8 @@ referenced as <code>*todo*</code>, but this is a detail hidden behind the API.
337 342
 </p>
338 343
 </div>
339 344
 
340
-<div id="outline-container-org28e1af7" class="outline-3">
341
-<h3 id="org28e1af7"><span class="section-number-3">2.1</span> List-level APIs</h3>
345
+<div id="outline-container-org066a36a" class="outline-3">
346
+<h3 id="org066a36a"><span class="section-number-3">2.1</span> List-level APIs</h3>
342 347
 <div class="outline-text-3" id="text-2-1">
343 348
 <p>
344 349
 These are functions for getting the todo list and clearing
... ...
@@ -347,7 +352,7 @@ and <code>clear-todos</code> for DELETE requests.
347 352
 </p>
348 353
 
349 354
 <div class="org-src-container">
350
-<pre class="src src-lisp" id="org5245d2d"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todos</span> <span style="color: #93a8c6;">()</span>
355
+<pre class="src src-lisp" id="orgb828d62"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todos</span> <span style="color: #93a8c6;">()</span>
351 356
   <span style="color: #93a8c6;">(</span>gmap:gmap <span style="font-weight: bold;">:seq</span>
352 357
              <span style="color: #b0b1a3;">(</span><span style="color: #F0DFAF;">lambda</span> <span style="color: #97b098;">(</span>_ b<span style="color: #97b098;">)</span>
353 358
                <span style="color: #97b098;">(</span><span style="color: #F0DFAF;">declare</span> <span style="color: #aebed8;">(</span>ignore _<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
... ...
@@ -362,8 +367,8 @@ and <code>clear-todos</code> for DELETE requests.
362 367
 </div>
363 368
 </div>
364 369
 
365
-<div id="outline-container-orgdb74c86" class="outline-3">
366
-<h3 id="orgdb74c86"><span class="section-number-3">2.2</span> Getting/Replacing a todo</h3>
370
+<div id="outline-container-org8f0d41e" class="outline-3">
371
+<h3 id="org8f0d41e"><span class="section-number-3">2.2</span> Getting/Replacing a todo</h3>
367 372
 <div class="outline-text-3" id="text-2-2">
368 373
 <p>
369 374
 This uses lisp's <a href="http://www.lispworks.com/documentation/HyperSpec/Body/05_a.htm">generalized references</a> to abstract away the
... ...
@@ -373,7 +378,7 @@ the GET request for a specific todo by id.
373 378
 </p>
374 379
 
375 380
 <div class="org-src-container">
376
-<pre class="src src-lisp" id="orgccc29e3"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todo</span> <span style="color: #93a8c6;">(</span>id<span style="color: #93a8c6;">)</span>
381
+<pre class="src src-lisp" id="org160aa97"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todo</span> <span style="color: #93a8c6;">(</span>id<span style="color: #93a8c6;">)</span>
377 382
   <span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">let</span> <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span>todo <span style="color: #aebed8;">(</span>fset:@ *todos* id<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
378 383
     todo<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
379 384
 
... ...
@@ -389,8 +394,8 @@ the GET request for a specific todo by id.
389 394
 </div>
390 395
 </div>
391 396
 
392
-<div id="outline-container-org0c6b1ff" class="outline-3">
393
-<h3 id="org0c6b1ff"><span class="section-number-3">2.3</span> Adding and modifying todos</h3>
397
+<div id="outline-container-org5e267ef" class="outline-3">
398
+<h3 id="org5e267ef"><span class="section-number-3">2.3</span> Adding and modifying todos</h3>
394 399
 <div class="outline-text-3" id="text-2-3">
395 400
 <p>
396 401
 <code>new-todo</code> is fairly trivial. It's main feature is that it has to
... ...
@@ -400,14 +405,19 @@ properly. <code>new-todo</code> backs POST requests to the root endpoint.
400 405
 </p>
401 406
 
402 407
 <div class="org-src-container">
403
-<pre class="src src-lisp" id="org4ac9cce"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">new-todo</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
408
+<pre class="src src-lisp" id="orgc33e5ab"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-host*</span>
409
+  <span style="color: #D0BF8F;">"localhost"</span><span style="color: #8c8c8c;">)</span>
410
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-port*</span>
411
+  5000<span style="color: #8c8c8c;">)</span>
412
+
413
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">new-todo</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
404 414
   <span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">let</span> <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span>id <span style="color: #aebed8;">(</span>next-id<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
405 415
     <span style="color: #b0b1a3;">(</span>setf <span style="color: #97b098;">(</span>todo id<span style="color: #97b098;">)</span>
406 416
           <span style="color: #97b098;">(</span>alexandria:alist-hash-table
407 417
            <span style="color: #aebed8;">(</span>rutilsx.threading:-&gt;&gt;
408 418
             value
409 419
             <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"completed"</span> 'yason:false<span style="color: #b0b0b3;">)</span>
410
-            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span> <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://localhost:5000/todo/~d"</span> id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
420
+            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span> <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://~a:~d/todo/~d"</span> *external-host* *external-port* id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
411 421
            <span style="font-weight: bold;">:test</span> 'equal<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
412 422
 </pre>
413 423
 </div>
... ...
@@ -420,7 +430,7 @@ todo endpoint for a specific ID.
420 430
 </p>
421 431
 
422 432
 <div class="org-src-container">
423
-<pre class="src src-lisp" id="orga4002c9"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">update-todo</span> <span style="color: #93a8c6;">(</span>id v<span style="color: #93a8c6;">)</span>
433
+<pre class="src src-lisp" id="org1d7bd54"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">update-todo</span> <span style="color: #93a8c6;">(</span>id v<span style="color: #93a8c6;">)</span>
424 434
   <span style="color: #93a8c6;">(</span>setf <span style="color: #b0b1a3;">(</span>todo id<span style="color: #b0b1a3;">)</span>
425 435
         <span style="color: #b0b1a3;">(</span>serapeum:merge-tables <span style="color: #97b098;">(</span>or <span style="color: #aebed8;">(</span>todo id<span style="color: #aebed8;">)</span>
426 436
                                    <span style="color: #aebed8;">(</span>make-hash-table <span style="font-weight: bold;">:test</span> 'equal<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
... ...
@@ -434,8 +444,8 @@ todo endpoint for a specific ID.
434 444
 </div>
435 445
 </div>
436 446
 
437
-<div id="outline-container-org3a3c9b0" class="outline-3">
438
-<h3 id="org3a3c9b0"><span class="section-number-3">2.4</span> Examples</h3>
447
+<div id="outline-container-org856ed57" class="outline-3">
448
+<h3 id="org856ed57"><span class="section-number-3">2.4</span> Examples</h3>
439 449
 <div class="outline-text-3" id="text-2-4">
440 450
 <div class="org-src-container">
441 451
 <pre class="src src-lisp"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
... ...
@@ -450,10 +460,10 @@ todo endpoint for a specific ID.
450 460
 </div>
451 461
 
452 462
 <pre class="example">
453
-(#&lt;hash-table "url": "http://localhost:5000/todo/95",
463
+(#&lt;hash-table "url": "http://localhost:5000/todo/121",
454 464
               "title": "get groceries",
455 465
               "completed": YASON:FALSE&gt;
456
- #&lt;hash-table "url": "http://localhost:5000/todo/96",
466
+ #&lt;hash-table "url": "http://localhost:5000/todo/122",
457 467
               "title": "write-better-documentation",
458 468
               "completed": YASON:FALSE&gt;)
459 469
 </pre>
... ...
@@ -461,13 +471,77 @@ todo endpoint for a specific ID.
461 471
 </div>
462 472
 </div>
463 473
 
464
-<div id="outline-container-orgec2861c" class="outline-2">
465
-<h2 id="orgec2861c"><span class="section-number-2">3</span> Source</h2>
474
+
475
+<div id="outline-container-org8f02b65" class="outline-2">
476
+<h2 id="org8f02b65"><span class="section-number-2">3</span> Routing</h2>
466 477
 <div class="outline-text-2" id="text-3">
467 478
 </div>
468
-<div id="outline-container-org98cfbdd" class="outline-3">
469
-<h3 id="org98cfbdd"><span class="section-number-3">3.1</span> model.lisp source code</h3>
479
+<div id="outline-container-org93dcda5" class="outline-3">
480
+<h3 id="org93dcda5"><span class="section-number-3">3.1</span> Routing utilities</h3>
470 481
 <div class="outline-text-3" id="text-3-1">
482
+<p>
483
+The core utility here is the <code>defroutes</code> macro.  This takes a
484
+sequence of endpoint descriptions which contain nested definitions
485
+for HTTP verbs and expands to ningle's functions for manipulating
486
+routes.
487
+</p>
488
+
489
+<div class="org-src-container">
490
+<pre class="src src-lisp"><span style="color: #8c8c8c;">(</span>macroexpand-1
491
+ '<span style="color: #93a8c6;">(</span>defroutes app
492
+   <span style="color: #b0b1a3;">(</span><span style="color: #D0BF8F;">"/"</span>
493
+    <span style="color: #97b098;">(</span><span style="font-weight: bold;">:GET</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">()</span> <span style="color: #b0b0b3;">(</span>todos<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
494
+    <span style="color: #97b098;">(</span><span style="font-weight: bold;">:POST</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">(</span>v<span style="color: #b0b0b3;">)</span> <span style="color: #b0b0b3;">(</span>new-todo v<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
495
+    <span style="color: #97b098;">(</span><span style="font-weight: bold;">:DELETE</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">()</span> <span style="color: #b0b0b3;">(</span>clear-todos<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
496
+</pre>
497
+</div>
498
+
499
+<pre class="example">
500
+(LET ((#:APP1855 APP))
501
+  (SETF (NINGLE/APP:ROUTE #:APP1855 "/" :METHOD METHOD)
502
+          (HANDLER NIL
503
+            (TODOS))
504
+        (NINGLE/APP:ROUTE #:APP1855 "/" :METHOD METHOD)
505
+          (HANDLER (V)
506
+            (NEW-TODO V))
507
+        (NINGLE/APP:ROUTE #:APP1855 "/" :METHOD METHOD)
508
+          (HANDLER NIL
509
+            (CLEAR-TODOS))))
510
+T
511
+</pre>
512
+
513
+<div class="org-src-container">
514
+<pre class="src src-lisp" id="org9d33ed2"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">defroutes</span> <span style="color: #93a8c6;">(</span>app <span style="color: #CC9393;">&amp;body</span> routes<span style="color: #93a8c6;">)</span>
515
+  <span style="color: #93a8c6;">(</span>alexandria:once-only <span style="color: #b0b1a3;">(</span>app<span style="color: #b0b1a3;">)</span>
516
+    `<span style="color: #b0b1a3;">(</span>setf
517
+      ,@<span style="color: #97b098;">(</span><span style="color: #F0DFAF;">loop</span> for <span style="color: #aebed8;">(</span>target . descriptors<span style="color: #aebed8;">)</span> in routes
518
+              append <span style="color: #aebed8;">(</span><span style="color: #F0DFAF;">loop</span> for <span style="color: #b0b0b3;">(</span>method callback<span style="color: #b0b0b3;">)</span> in descriptors
519
+                           append `<span style="color: #b0b0b3;">(</span><span style="color: #90a890;">(</span>ningle:route ,app ,target
520
+                                                  <span style="font-weight: bold;">:method</span> method<span style="color: #90a890;">)</span>
521
+                                    ,callback<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
522
+
523
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">success</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
524
+  <span style="color: #93a8c6;">(</span>list 200 nil value<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
525
+
526
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">handler</span> <span style="color: #93a8c6;">(</span><span style="color: #b0b1a3;">(</span><span style="color: #CC9393;">&amp;optional</span> <span style="color: #97b098;">(</span>sym <span style="color: #aebed8;">(</span>gensym <span style="color: #D0BF8F;">"PARAMS"</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span> <span style="color: #CC9393;">&amp;body</span> body<span style="color: #93a8c6;">)</span>
527
+  `<span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">lambda</span> <span style="color: #b0b1a3;">(</span>,sym<span style="color: #b0b1a3;">)</span>
528
+     <span style="color: #b0b1a3;">(</span><span style="color: #F0DFAF;">declare</span> <span style="color: #97b098;">(</span>ignorable ,sym<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
529
+     <span style="color: #b0b1a3;">(</span>success
530
+      <span style="color: #97b098;">(</span>fwoar.lack.json.middleware:wrap-result
531
+       <span style="color: #aebed8;">(</span><span style="color: #F0DFAF;">progn</span> ,@body<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
532
+</pre>
533
+</div>
534
+</div>
535
+</div>
536
+</div>
537
+
538
+<div id="outline-container-orgdec30ec" class="outline-2">
539
+<h2 id="orgdec30ec"><span class="section-number-2">4</span> Source</h2>
540
+<div class="outline-text-2" id="text-4">
541
+</div>
542
+<div id="outline-container-org1cf20cf" class="outline-3">
543
+<h3 id="org1cf20cf"><span class="section-number-3">4.1</span> model.lisp source code</h3>
544
+<div class="outline-text-3" id="text-4-1">
471 545
 <div class="org-src-container">
472 546
 <pre class="src src-lisp"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::package-include][package-include]]</span>
473 547
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
... ...
@@ -517,6 +591,11 @@ todo endpoint for a specific ID.
517 591
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">todo-accessor ends here</span>
518 592
 
519 593
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::new-todo][new-todo]]</span>
594
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-host*</span>
595
+  <span style="color: #D0BF8F;">"localhost"</span><span style="color: #8c8c8c;">)</span>
596
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-port*</span>
597
+  5000<span style="color: #8c8c8c;">)</span>
598
+
520 599
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">new-todo</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
521 600
   <span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">let</span> <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span>id <span style="color: #aebed8;">(</span>next-id<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
522 601
     <span style="color: #b0b1a3;">(</span>setf <span style="color: #97b098;">(</span>todo id<span style="color: #97b098;">)</span>
... ...
@@ -524,7 +603,7 @@ todo endpoint for a specific ID.
524 603
            <span style="color: #aebed8;">(</span>rutilsx.threading:-&gt;&gt;
525 604
             value
526 605
             <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"completed"</span> 'yason:false<span style="color: #b0b0b3;">)</span>
527
-            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span> <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://localhost:5000/todo/~d"</span> id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
606
+            <span style="color: #b0b0b3;">(</span>acons <span style="color: #D0BF8F;">"url"</span> <span style="color: #90a890;">(</span>format nil <span style="color: #D0BF8F;">"http://~a:~d/todo/~d"</span> *external-host* *external-port* id<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
528 607
            <span style="font-weight: bold;">:test</span> 'equal<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
529 608
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">new-todo ends here</span>
530 609
 
... ...
@@ -548,23 +627,25 @@ todo endpoint for a specific ID.
548 627
 </div>
549 628
 </div>
550 629
 
551
-<div id="outline-container-orgd68289a" class="outline-3">
552
-<h3 id="orgd68289a"><span class="section-number-3">3.2</span> routing.lisp source</h3>
553
-<div class="outline-text-3" id="text-3-2">
630
+<div id="outline-container-orgbce9205" class="outline-3">
631
+<h3 id="orgbce9205"><span class="section-number-3">4.2</span> routing.lisp source</h3>
632
+<div class="outline-text-3" id="text-4-2">
554 633
 <div class="org-src-container">
555
-<pre class="src src-lisp"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
634
+<pre class="src src-lisp"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::package-include][package-include]]</span>
635
+<span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
556 636
 
637
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">package-include ends here</span>
638
+
639
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::routing-helpers][routing-helpers]]</span>
557 640
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defmacro</span> <span style="color: #8CD0D3;">defroutes</span> <span style="color: #93a8c6;">(</span>app <span style="color: #CC9393;">&amp;body</span> routes<span style="color: #93a8c6;">)</span>
558
-  <span style="color: #D0BF8F;">"Define a set of routes for given paths. the ROUTES parameter expects this format:</span>
559
-<span style="color: #D0BF8F;">   ((\"/path/to/{route}\" :method :POST) route-callback) the AS-ROUTE macro helps one</span>
560
-<span style="color: #D0BF8F;">   avoid binding function values to the route for flexibility."</span>
561 641
   <span style="color: #93a8c6;">(</span>alexandria:once-only <span style="color: #b0b1a3;">(</span>app<span style="color: #b0b1a3;">)</span>
562
-    `<span style="color: #b0b1a3;">(</span><span style="color: #F0DFAF;">progn</span>
563
-       ,@<span style="color: #97b098;">(</span><span style="color: #F0DFAF;">loop</span> for <span style="color: #aebed8;">(</span><span style="color: #b0b0b3;">(</span>target <span style="color: #CC9393;">&amp;key</span> method<span style="color: #b0b0b3;">)</span> callback<span style="color: #aebed8;">)</span> in routes
564
-               collect `<span style="color: #aebed8;">(</span>setf <span style="color: #b0b0b3;">(</span>ningle:route ,app ,target <span style="font-weight: bold;">:method</span> ,<span style="color: #90a890;">(</span>or method <span style="font-weight: bold;">:GET</span><span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span> ,callback<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
565
-
642
+    `<span style="color: #b0b1a3;">(</span>setf
643
+      ,@<span style="color: #97b098;">(</span><span style="color: #F0DFAF;">loop</span> for <span style="color: #aebed8;">(</span>target . descriptors<span style="color: #aebed8;">)</span> in routes
644
+              append <span style="color: #aebed8;">(</span><span style="color: #F0DFAF;">loop</span> for <span style="color: #b0b0b3;">(</span>method callback<span style="color: #b0b0b3;">)</span> in descriptors
645
+                           append `<span style="color: #b0b0b3;">(</span><span style="color: #90a890;">(</span>ningle:route ,app ,target
646
+                                                  <span style="font-weight: bold;">:method</span> method<span style="color: #90a890;">)</span>
647
+                                    ,callback<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
566 648
 
567
-<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing</span>
568 649
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">success</span> <span style="color: #93a8c6;">(</span>value<span style="color: #93a8c6;">)</span>
569 650
   <span style="color: #93a8c6;">(</span>list 200 nil value<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
570 651
 
... ...
@@ -574,30 +655,32 @@ todo endpoint for a specific ID.
574 655
      <span style="color: #b0b1a3;">(</span>success
575 656
       <span style="color: #97b098;">(</span>fwoar.lack.json.middleware:wrap-result
576 657
        <span style="color: #aebed8;">(</span><span style="color: #F0DFAF;">progn</span> ,@body<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
658
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing-helpers ends here</span>
577 659
 
660
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing</span>
578 661
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">get-id</span> <span style="color: #93a8c6;">(</span>params<span style="color: #93a8c6;">)</span>
579 662
   <span style="color: #93a8c6;">(</span>parse-integer <span style="color: #b0b1a3;">(</span>serapeum:assocdr <span style="font-weight: bold;">:id</span> params<span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
580 663
 
581 664
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">setup-routes</span> <span style="color: #93a8c6;">(</span>app<span style="color: #93a8c6;">)</span>
582 665
   <span style="color: #93a8c6;">(</span>defroutes app
583
-    <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span><span style="color: #D0BF8F;">"/"</span> <span style="font-weight: bold;">:method</span> <span style="font-weight: bold;">:GET</span><span style="color: #97b098;">)</span>            <span style="color: #97b098;">(</span>handler <span style="color: #aebed8;">()</span> <span style="color: #aebed8;">(</span>todos<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
584
-    <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span><span style="color: #D0BF8F;">"/"</span> <span style="font-weight: bold;">:method</span> <span style="font-weight: bold;">:POST</span><span style="color: #97b098;">)</span>           <span style="color: #97b098;">(</span>handler <span style="color: #aebed8;">(</span>v<span style="color: #aebed8;">)</span> <span style="color: #aebed8;">(</span>new-todo v<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
585
-    <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span><span style="color: #D0BF8F;">"/"</span> <span style="font-weight: bold;">:method</span> <span style="font-weight: bold;">:DELETE</span><span style="color: #97b098;">)</span>         <span style="color: #97b098;">(</span>handler <span style="color: #aebed8;">()</span> <span style="color: #aebed8;">(</span>clear-todos<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
586
-    <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span><span style="color: #D0BF8F;">"/todo/:id"</span> <span style="font-weight: bold;">:method</span> <span style="font-weight: bold;">:GET</span><span style="color: #97b098;">)</span>    <span style="color: #97b098;">(</span>handler <span style="color: #aebed8;">(</span>v<span style="color: #aebed8;">)</span> <span style="color: #aebed8;">(</span>todo <span style="color: #b0b0b3;">(</span>get-id v<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
587
-    <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span><span style="color: #D0BF8F;">"/todo/:id"</span> <span style="font-weight: bold;">:method</span> <span style="font-weight: bold;">:DELETE</span><span style="color: #97b098;">)</span> <span style="color: #97b098;">(</span>handler <span style="color: #aebed8;">(</span>v<span style="color: #aebed8;">)</span>
588
-                                     <span style="color: #aebed8;">(</span>delete-todo <span style="color: #b0b0b3;">(</span>get-id v<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span>
589
-                                     nil<span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
590
-    <span style="color: #b0b1a3;">(</span><span style="color: #97b098;">(</span><span style="color: #D0BF8F;">"/todo/:id"</span> <span style="font-weight: bold;">:method</span> <span style="font-weight: bold;">:PATCH</span><span style="color: #97b098;">)</span>  <span style="color: #97b098;">(</span>handler <span style="color: #aebed8;">(</span>v<span style="color: #aebed8;">)</span>
591
-                                     <span style="color: #aebed8;">(</span>update-todo <span style="color: #b0b0b3;">(</span>get-id v<span style="color: #b0b0b3;">)</span> 
592
-                                                  <span style="color: #b0b0b3;">(</span>remove <span style="font-weight: bold;">:id</span> v <span style="font-weight: bold;">:key</span> #'car<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
666
+    <span style="color: #b0b1a3;">(</span><span style="color: #D0BF8F;">"/"</span> <span style="color: #97b098;">(</span><span style="font-weight: bold;">:GET</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">()</span> <span style="color: #b0b0b3;">(</span>todos<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
667
+         <span style="color: #97b098;">(</span><span style="font-weight: bold;">:POST</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">(</span>v<span style="color: #b0b0b3;">)</span> <span style="color: #b0b0b3;">(</span>new-todo v<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
668
+         <span style="color: #97b098;">(</span><span style="font-weight: bold;">:DELETE</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">()</span> <span style="color: #b0b0b3;">(</span>clear-todos<span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span>
669
+    <span style="color: #b0b1a3;">(</span><span style="color: #D0BF8F;">"/todo/:id"</span> <span style="color: #97b098;">(</span><span style="font-weight: bold;">:GET</span>    <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">(</span>v<span style="color: #b0b0b3;">)</span> <span style="color: #b0b0b3;">(</span>todo <span style="color: #90a890;">(</span>get-id v<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
670
+                 <span style="color: #97b098;">(</span><span style="font-weight: bold;">:DELETE</span> <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">(</span>v<span style="color: #b0b0b3;">)</span>
671
+                            <span style="color: #b0b0b3;">(</span>delete-todo <span style="color: #90a890;">(</span>get-id v<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span>
672
+                            nil<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
673
+                 <span style="color: #97b098;">(</span><span style="font-weight: bold;">:PATCH</span>  <span style="color: #aebed8;">(</span>handler <span style="color: #b0b0b3;">(</span>v<span style="color: #b0b0b3;">)</span>
674
+                            <span style="color: #b0b0b3;">(</span>update-todo <span style="color: #90a890;">(</span>get-id v<span style="color: #90a890;">)</span> 
675
+                                         <span style="color: #90a890;">(</span>remove <span style="font-weight: bold;">:id</span> v <span style="font-weight: bold;">:key</span> #'car<span style="color: #90a890;">)</span><span style="color: #b0b0b3;">)</span><span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span><span style="color: #b0b1a3;">)</span><span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
593 676
 </pre>
594 677
 </div>
595 678
 </div>
596 679
 </div>
597 680
 
598
-<div id="outline-container-org54c59b7" class="outline-3">
599
-<h3 id="org54c59b7"><span class="section-number-3">3.3</span> main.lisp source</h3>
600
-<div class="outline-text-3" id="text-3-3">
681
+<div id="outline-container-orgc91e7f6" class="outline-3">
682
+<h3 id="orgc91e7f6"><span class="section-number-3">4.3</span> main.lisp source</h3>
683
+<div class="outline-text-3" id="text-4-3">
601 684
 <div class="org-src-container">
602 685
 <pre class="src src-lisp"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">in-package</span> <span style="font-weight: bold;">:fwoar.todo</span><span style="color: #8c8c8c;">)</span>
603 686
 
... ...
@@ -642,7 +725,7 @@ todo endpoint for a specific ID.
642 725
 </div>
643 726
 <div id="postamble" class="status">
644 727
 <p class="author">Author: Langley</p>
645
-<p class="date">Created: 2019-08-29 Thu 13:51</p>
728
+<p class="date">Created: 2019-08-30 Fri 02:00</p>
646 729
 <p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
647 730
 </div>
648 731
 </body>
... ...
@@ -47,6 +47,11 @@
47 47
 ;; todo-accessor ends here
48 48
 
49 49
 ;; [[file:~/git_repos/lisp-sandbox/todo/README.org::new-todo][new-todo]]
50
+(defvar *external-host*
51
+  "localhost")
52
+(defvar *external-port*
53
+  5000)
54
+
50 55
 (defun new-todo (value)
51 56
   (let ((id (next-id)))
52 57
     (setf (todo id)
... ...
@@ -54,7 +59,7 @@
54 59
            (rutilsx.threading:->>
55 60
             value
56 61
             (acons "completed" 'yason:false)
57
-            (acons "url" (format nil "http://localhost:5000/todo/~d" id)))
62
+            (acons "url" (format nil "http://~a:~d/todo/~d" *external-host* *external-port* id)))
58 63
            :test 'equal))))
59 64
 ;; new-todo ends here
60 65
 
... ...
@@ -1,16 +1,19 @@
1
+;; [[file:~/git_repos/lisp-sandbox/todo/README.org::*routing.lisp%20source][routing.lisp source:1]]
2
+;; [[file:~/git_repos/lisp-sandbox/todo/README.org::package-include][package-include]]
1 3
 (in-package :fwoar.todo)
2 4
 
5
+;; package-include ends here
6
+
7
+;; [[file:~/git_repos/lisp-sandbox/todo/README.org::routing-helpers][routing-helpers]]
3 8
 (defmacro defroutes (app &body routes)
4
-  "Define a set of routes for given paths. the ROUTES parameter expects this format:
5
-   ((\"/path/to/{route}\" :method :POST) route-callback) the AS-ROUTE macro helps one
6
-   avoid binding function values to the route for flexibility."
7 9
   (alexandria:once-only (app)
8
-    `(progn
9
-       ,@(loop for ((target &key method) callback) in routes
10
-               collect `(setf (ningle:route ,app ,target :method ,(or method :GET)) ,callback)))))
11
-
10
+    `(setf
11
+      ,@(loop for (target . descriptors) in routes
12
+              append (loop for (method callback) in descriptors
13
+                           append `((ningle:route ,app ,target
14
+                                                  :method method)
15
+                                    ,callback))))))
12 16
 
13
-;; routing
14 17
 (defun success (value)
15 18
   (list 200 nil value))
16 19
 
... ...
@@ -20,19 +23,22 @@
20 23
      (success
21 24
       (fwoar.lack.json.middleware:wrap-result
22 25
        (progn ,@body)))))
26
+;; routing-helpers ends here
23 27
 
28
+;; routing
24 29
 (defun get-id (params)
25 30
   (parse-integer (serapeum:assocdr :id params)))
26 31
 
27 32
 (defun setup-routes (app)
28 33
   (defroutes app
29
-    (("/" :method :GET)            (handler () (todos)))
30
-    (("/" :method :POST)           (handler (v) (new-todo v)))
31
-    (("/" :method :DELETE)         (handler () (clear-todos)))
32
-    (("/todo/:id" :method :GET)    (handler (v) (todo (get-id v))))
33
-    (("/todo/:id" :method :DELETE) (handler (v)
34
-                                     (delete-todo (get-id v))
35
-                                     nil))
36
-    (("/todo/:id" :method :PATCH)  (handler (v)
37
-                                     (update-todo (get-id v) 
38
-                                                  (remove :id v :key #'car))))))
34
+    ("/" (:GET (handler () (todos)))
35
+         (:POST (handler (v) (new-todo v)))
36
+         (:DELETE (handler () (clear-todos))))
37
+    ("/todo/:id" (:GET    (handler (v) (todo (get-id v))))
38
+                 (:DELETE (handler (v)
39
+                            (delete-todo (get-id v))
40
+                            nil))
41
+                 (:PATCH  (handler (v)
42
+                            (update-todo (get-id v) 
43
+                                         (remove :id v :key #'car)))))))
44
+;; routing.lisp source:1 ends here