git.fiddlerwoaroof.com
Browse code

documentation: finish documenting routing

Ed Langley authored on 30/08/2019 07:15:55
Showing 3 changed files
... ...
@@ -132,6 +132,22 @@
132 132
    sequence of endpoint descriptions which contain nested definitions
133 133
    for HTTP verbs and expands to ningle's functions for manipulating
134 134
    routes.
135
+
136
+   #+NAME: defroutes
137
+   #+BEGIN_SRC lisp
138
+     (defmacro defroutes (app &body routes)
139
+       (alexandria:once-only (app)
140
+         `(setf
141
+           ,@(loop for (target . descriptors) in routes
142
+                   append (loop for (method callback) in descriptors
143
+                                append `((ningle:route ,app ,target
144
+                                                       :method method)
145
+                                         ,callback))))))
146
+   #+END_SRC
147
+   
148
+   This macro organizes all the HTTP verbs for a given endpoint under
149
+   the path to that endpoint. A more complete version might allow for
150
+   a list of verbs =(:GET :POST)= in the head of each handler clause.
135 151
    
136 152
    #+BEGIN_SRC lisp :exports both :tangle no :results verbatim
137 153
      (macroexpand-1
... ...
@@ -141,6 +157,7 @@
141 157
          (:POST (handler (v) (new-todo v)))
142 158
          (:DELETE (handler () (clear-todos))))))
143 159
    #+END_SRC
160
+   
144 161
 
145 162
    #+RESULTS:
146 163
    #+begin_example
... ...
@@ -156,20 +173,16 @@
156 173
                (CLEAR-TODOS))))
157 174
    T
158 175
    #+end_example
176
+   
177
+   Finally, there are some simple helpers to handle some of the
178
+   boilerplate in a clack webserver.  Of particular interest is the
179
+   =handler= macro, which (since this is a json-only API) makes sure
180
+   that all the API results get JSON encoded.
159 181
 
160 182
    #+NAME: routing-helpers
161 183
    #+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 184
      (defun success (value)
172
-       (list 200 nil value))
185
+       (list 200 '(:conent-type "application/json") value))
173 186
 
174 187
      (defmacro handler ((&optional (sym (gensym "PARAMS"))) &body body)
175 188
        `(lambda (,sym)
... ...
@@ -177,7 +190,36 @@
177 190
           (success
178 191
            (fwoar.lack.json.middleware:wrap-result
179 192
             (progn ,@body)))))
180
-   #+end_SRC
193
+   #+END_SRC
194
+   
195
+** todo routes
196
+
197
+   =setup-routes= binds the endpoints to handlers: "/" to handlers
198
+   that handle the todo lists while "/todo/:id" to handlers that
199
+   handle individual todos.  The =:id= indicates that the
200
+   corresponding segment of the path is bound to =:id= in the param
201
+   alist. =get-id= handles this, and extracts an integer for the id
202
+   (since we are using successive integers for the todo ids).
203
+
204
+   #+NAME: todo-routes
205
+   #+BEGIN_SRC lisp
206
+     ;; routing
207
+     (defun get-id (params)
208
+       (parse-integer (serapeum:assocdr :id params)))
209
+
210
+     (defun setup-routes (app)
211
+       (defroutes app
212
+         ("/" (:GET (handler () (todos)))
213
+              (:POST (handler (v) (new-todo v)))
214
+              (:DELETE (handler () (clear-todos))))
215
+         ("/todo/:id" (:GET    (handler (v) (todo (get-id v))))
216
+                      (:DELETE (handler (v)
217
+                                 (delete-todo (get-id v))
218
+                                 nil))
219
+                      (:PATCH  (handler (v)
220
+                                 (update-todo (get-id v) 
221
+                                              (remove :id v :key #'car)))))))
222
+   #+END_SRC
181 223
 
182 224
 * Source
183 225
 ** model.lisp source code
... ...
@@ -206,24 +248,11 @@
206 248
    #+BEGIN_SRC lisp :tangle routing.lisp :noweb yes :comments noweb 
207 249
      <<package-include>>
208 250
 
209
-     <<routing-helpers>>
251
+     <<defroutes>>
210 252
 
211
-     ;; routing
212
-     (defun get-id (params)
213
-       (parse-integer (serapeum:assocdr :id params)))
253
+     <<routing-helpers>>
214 254
 
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)))))))
255
+     <<todo-routes>>
227 256
    #+END_SRC
228 257
 
229 258
 ** 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-30 Fri 02:00 -->
6
+<!-- 2019-08-30 Fri 02:15 -->
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,33 +285,34 @@ 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="#orgf719c2d">1. Setup</a></li>
289
-<li><a href="#org5024541">2. todo API</a>
288
+<li><a href="#org2b6564f">1. Setup</a></li>
289
+<li><a href="#org152326b">2. todo API</a>
290 290
 <ul>
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>
291
+<li><a href="#org006b1f9">2.1. List-level APIs</a></li>
292
+<li><a href="#orge19ce57">2.2. Getting/Replacing a todo</a></li>
293
+<li><a href="#orgf298702">2.3. Adding and modifying todos</a></li>
294
+<li><a href="#orgd0dd01c">2.4. Examples</a></li>
295 295
 </ul>
296 296
 </li>
297
-<li><a href="#org8f02b65">3. Routing</a>
297
+<li><a href="#org42229a6">3. Routing</a>
298 298
 <ul>
299
-<li><a href="#org93dcda5">3.1. Routing utilities</a></li>
299
+<li><a href="#org84376ba">3.1. Routing utilities</a></li>
300
+<li><a href="#orgb1f34fd">3.2. todo routes</a></li>
300 301
 </ul>
301 302
 </li>
302
-<li><a href="#orgdec30ec">4. Source</a>
303
+<li><a href="#org7d68735">4. Source</a>
303 304
 <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>
305
+<li><a href="#org8b89d94">4.1. model.lisp source code</a></li>
306
+<li><a href="#org031a2d2">4.2. routing.lisp source</a></li>
307
+<li><a href="#org04fe926">4.3. main.lisp source</a></li>
307 308
 </ul>
308 309
 </li>
309 310
 </ul>
310 311
 </div>
311 312
 </div>
312 313
 
313
-<div id="outline-container-orgf719c2d" class="outline-2">
314
-<h2 id="orgf719c2d"><span class="section-number-2">1</span> Setup</h2>
314
+<div id="outline-container-org2b6564f" class="outline-2">
315
+<h2 id="org2b6564f"><span class="section-number-2">1</span> Setup</h2>
315 316
 <div class="outline-text-2" id="text-1">
316 317
 <ul class="org-ul">
317 318
 <li><code class="src src-sh">git clone https://github.com/fiddlerwoaroof/data-lens.git ~/quicklisp/local-projects/data-lens</code></li>
... ...
@@ -331,8 +332,8 @@ After this, all the tests <a href="http://www.todobackend.com/specs/index.html?h
331 332
 </div>
332 333
 </div>
333 334
 
334
-<div id="outline-container-org5024541" class="outline-2">
335
-<h2 id="org5024541"><span class="section-number-2">2</span> todo API</h2>
335
+<div id="outline-container-org152326b" class="outline-2">
336
+<h2 id="org152326b"><span class="section-number-2">2</span> todo API</h2>
336 337
 <div class="outline-text-2" id="text-2">
337 338
 <p>
338 339
 We use a fairly simple structure for our "database": a fset map (a
... ...
@@ -342,8 +343,8 @@ referenced as <code>*todo*</code>, but this is a detail hidden behind the API.
342 343
 </p>
343 344
 </div>
344 345
 
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>
346
+<div id="outline-container-org006b1f9" class="outline-3">
347
+<h3 id="org006b1f9"><span class="section-number-3">2.1</span> List-level APIs</h3>
347 348
 <div class="outline-text-3" id="text-2-1">
348 349
 <p>
349 350
 These are functions for getting the todo list and clearing
... ...
@@ -352,7 +353,7 @@ and <code>clear-todos</code> for DELETE requests.
352 353
 </p>
353 354
 
354 355
 <div class="org-src-container">
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>
356
+<pre class="src src-lisp" id="org8067877"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defun</span> <span style="color: #8CD0D3;">todos</span> <span style="color: #93a8c6;">()</span>
356 357
   <span style="color: #93a8c6;">(</span>gmap:gmap <span style="font-weight: bold;">:seq</span>
357 358
              <span style="color: #b0b1a3;">(</span><span style="color: #F0DFAF;">lambda</span> <span style="color: #97b098;">(</span>_ b<span style="color: #97b098;">)</span>
358 359
                <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>
... ...
@@ -367,8 +368,8 @@ and <code>clear-todos</code> for DELETE requests.
367 368
 </div>
368 369
 </div>
369 370
 
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>
371
+<div id="outline-container-orge19ce57" class="outline-3">
372
+<h3 id="orge19ce57"><span class="section-number-3">2.2</span> Getting/Replacing a todo</h3>
372 373
 <div class="outline-text-3" id="text-2-2">
373 374
 <p>
374 375
 This uses lisp's <a href="http://www.lispworks.com/documentation/HyperSpec/Body/05_a.htm">generalized references</a> to abstract away the
... ...
@@ -378,7 +379,7 @@ the GET request for a specific todo by id.
378 379
 </p>
379 380
 
380 381
 <div class="org-src-container">
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>
382
+<pre class="src src-lisp" id="orga61555f"><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>
382 383
   <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>
383 384
     todo<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
384 385
 
... ...
@@ -394,8 +395,8 @@ the GET request for a specific todo by id.
394 395
 </div>
395 396
 </div>
396 397
 
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>
398
+<div id="outline-container-orgf298702" class="outline-3">
399
+<h3 id="orgf298702"><span class="section-number-3">2.3</span> Adding and modifying todos</h3>
399 400
 <div class="outline-text-3" id="text-2-3">
400 401
 <p>
401 402
 <code>new-todo</code> is fairly trivial. It's main feature is that it has to
... ...
@@ -405,7 +406,7 @@ properly. <code>new-todo</code> backs POST requests to the root endpoint.
405 406
 </p>
406 407
 
407 408
 <div class="org-src-container">
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
+<pre class="src src-lisp" id="org525fb01"><span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-host*</span>
409 410
   <span style="color: #D0BF8F;">"localhost"</span><span style="color: #8c8c8c;">)</span>
410 411
 <span style="color: #8c8c8c;">(</span><span style="color: #F0DFAF;">defvar</span> <span style="color: #DC8CC3;">*external-port*</span>
411 412
   5000<span style="color: #8c8c8c;">)</span>
... ...
@@ -430,7 +431,7 @@ todo endpoint for a specific ID.
430 431
 </p>
431 432
 
432 433
 <div class="org-src-container">
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>
434
+<pre class="src src-lisp" id="org0d08c54"><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>
434 435
   <span style="color: #93a8c6;">(</span>setf <span style="color: #b0b1a3;">(</span>todo id<span style="color: #b0b1a3;">)</span>
435 436
         <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>
436 437
                                    <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>
... ...
@@ -444,8 +445,8 @@ todo endpoint for a specific ID.
444 445
 </div>
445 446
 </div>
446 447
 
447
-<div id="outline-container-org856ed57" class="outline-3">
448
-<h3 id="org856ed57"><span class="section-number-3">2.4</span> Examples</h3>
448
+<div id="outline-container-orgd0dd01c" class="outline-3">
449
+<h3 id="orgd0dd01c"><span class="section-number-3">2.4</span> Examples</h3>
449 450
 <div class="outline-text-3" id="text-2-4">
450 451
 <div class="org-src-container">
451 452
 <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>
... ...
@@ -460,10 +461,10 @@ todo endpoint for a specific ID.
460 461
 </div>
461 462
 
462 463
 <pre class="example">
463
-(#&lt;hash-table "url": "http://localhost:5000/todo/121",
464
+(#&lt;hash-table "url": "http://localhost:5000/todo/129",
464 465
               "title": "get groceries",
465 466
               "completed": YASON:FALSE&gt;
466
- #&lt;hash-table "url": "http://localhost:5000/todo/122",
467
+ #&lt;hash-table "url": "http://localhost:5000/todo/130",
467 468
               "title": "write-better-documentation",
468 469
               "completed": YASON:FALSE&gt;)
469 470
 </pre>
... ...
@@ -472,12 +473,12 @@ todo endpoint for a specific ID.
472 473
 </div>
473 474
 
474 475
 
475
-<div id="outline-container-org8f02b65" class="outline-2">
476
-<h2 id="org8f02b65"><span class="section-number-2">3</span> Routing</h2>
476
+<div id="outline-container-org42229a6" class="outline-2">
477
+<h2 id="org42229a6"><span class="section-number-2">3</span> Routing</h2>
477 478
 <div class="outline-text-2" id="text-3">
478 479
 </div>
479
-<div id="outline-container-org93dcda5" class="outline-3">
480
-<h3 id="org93dcda5"><span class="section-number-3">3.1</span> Routing utilities</h3>
480
+<div id="outline-container-org84376ba" class="outline-3">
481
+<h3 id="org84376ba"><span class="section-number-3">3.1</span> Routing utilities</h3>
481 482
 <div class="outline-text-3" id="text-3-1">
482 483
 <p>
483 484
 The core utility here is the <code>defroutes</code> macro.  This takes a
... ...
@@ -486,6 +487,24 @@ for HTTP verbs and expands to ningle's functions for manipulating
486 487
 routes.
487 488
 </p>
488 489
 
490
+<div class="org-src-container">
491
+<pre class="src src-lisp" id="org6e29078"><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>
492
+  <span style="color: #93a8c6;">(</span>alexandria:once-only <span style="color: #b0b1a3;">(</span>app<span style="color: #b0b1a3;">)</span>
493
+    `<span style="color: #b0b1a3;">(</span>setf
494
+      ,@<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
495
+              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
496
+                           append `<span style="color: #b0b0b3;">(</span><span style="color: #90a890;">(</span>ningle:route ,app ,target
497
+                                                  <span style="font-weight: bold;">:method</span> method<span style="color: #90a890;">)</span>
498
+                                    ,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>
499
+</pre>
500
+</div>
501
+
502
+<p>
503
+This macro organizes all the HTTP verbs for a given endpoint under
504
+the path to that endpoint. A more complete version might allow for
505
+a list of verbs <code>(:GET :POST)</code> in the head of each handler clause.
506
+</p>
507
+
489 508
 <div class="org-src-container">
490 509
 <pre class="src src-lisp"><span style="color: #8c8c8c;">(</span>macroexpand-1
491 510
  '<span style="color: #93a8c6;">(</span>defroutes app
... ...
@@ -496,32 +515,31 @@ routes.
496 515
 </pre>
497 516
 </div>
498 517
 
518
+
499 519
 <pre class="example">
500
-(LET ((#:APP1855 APP))
501
-  (SETF (NINGLE/APP:ROUTE #:APP1855 "/" :METHOD METHOD)
520
+(LET ((#:APP1859 APP))
521
+  (SETF (NINGLE/APP:ROUTE #:APP1859 "/" :METHOD METHOD)
502 522
           (HANDLER NIL
503 523
             (TODOS))
504
-        (NINGLE/APP:ROUTE #:APP1855 "/" :METHOD METHOD)
524
+        (NINGLE/APP:ROUTE #:APP1859 "/" :METHOD METHOD)
505 525
           (HANDLER (V)
506 526
             (NEW-TODO V))
507
-        (NINGLE/APP:ROUTE #:APP1855 "/" :METHOD METHOD)
527
+        (NINGLE/APP:ROUTE #:APP1859 "/" :METHOD METHOD)
508 528
           (HANDLER NIL
509 529
             (CLEAR-TODOS))))
510 530
 T
511 531
 </pre>
512 532
 
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>
533
+<p>
534
+Finally, there are some simple helpers to handle some of the
535
+boilerplate in a clack webserver.  Of particular interest is the
536
+<code>handler</code> macro, which (since this is a json-only API) makes sure
537
+that all the API results get JSON encoded.
538
+</p>
522 539
 
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>
540
+<div class="org-src-container">
541
+<pre class="src src-lisp" id="org83a717f"><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>
542
+  <span style="color: #93a8c6;">(</span>list 200 '<span style="color: #b0b1a3;">(</span><span style="font-weight: bold;">:conent-type</span> <span style="color: #D0BF8F;">"application/json"</span><span style="color: #b0b1a3;">)</span> value<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
525 543
 
526 544
 <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 545
   `<span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">lambda</span> <span style="color: #b0b1a3;">(</span>,sym<span style="color: #b0b1a3;">)</span>
... ...
@@ -533,14 +551,48 @@ T
533 551
 </div>
534 552
 </div>
535 553
 </div>
554
+
555
+<div id="outline-container-orgb1f34fd" class="outline-3">
556
+<h3 id="orgb1f34fd"><span class="section-number-3">3.2</span> todo routes</h3>
557
+<div class="outline-text-3" id="text-3-2">
558
+<p>
559
+<code>setup-routes</code> binds the endpoints to handlers: "<i>" to handlers
560
+that handle the todo lists while "/todo</i>:id" to handlers that
561
+handle individual todos.  The <code>:id</code> indicates that the
562
+corresponding segment of the path is bound to <code>:id</code> in the param
563
+alist. <code>get-id</code> handles this, and extracts an integer for the id
564
+(since we are using successive integers for the todo ids).
565
+</p>
566
+
567
+<div class="org-src-container">
568
+<pre class="src src-lisp" id="orgceff44a"><span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing</span>
569
+<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>
570
+  <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>
571
+
572
+<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>
573
+  <span style="color: #93a8c6;">(</span>defroutes app
574
+    <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>
575
+         <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>
576
+         <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>
577
+    <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>
578
+                 <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>
579
+                            <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>
580
+                            nil<span style="color: #aebed8;">)</span><span style="color: #97b098;">)</span>
581
+                 <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>
582
+                            <span style="color: #b0b0b3;">(</span>update-todo <span style="color: #90a890;">(</span>get-id v<span style="color: #90a890;">)</span> 
583
+                                         <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>
584
+</pre>
585
+</div>
586
+</div>
587
+</div>
536 588
 </div>
537 589
 
538
-<div id="outline-container-orgdec30ec" class="outline-2">
539
-<h2 id="orgdec30ec"><span class="section-number-2">4</span> Source</h2>
590
+<div id="outline-container-org7d68735" class="outline-2">
591
+<h2 id="org7d68735"><span class="section-number-2">4</span> Source</h2>
540 592
 <div class="outline-text-2" id="text-4">
541 593
 </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>
594
+<div id="outline-container-org8b89d94" class="outline-3">
595
+<h3 id="org8b89d94"><span class="section-number-3">4.1</span> model.lisp source code</h3>
544 596
 <div class="outline-text-3" id="text-4-1">
545 597
 <div class="org-src-container">
546 598
 <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>
... ...
@@ -627,8 +679,8 @@ T
627 679
 </div>
628 680
 </div>
629 681
 
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>
682
+<div id="outline-container-org031a2d2" class="outline-3">
683
+<h3 id="org031a2d2"><span class="section-number-3">4.2</span> routing.lisp source</h3>
632 684
 <div class="outline-text-3" id="text-4-2">
633 685
 <div class="org-src-container">
634 686
 <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>
... ...
@@ -636,7 +688,7 @@ T
636 688
 
637 689
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">package-include ends here</span>
638 690
 
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>
691
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::defroutes][defroutes]]</span>
640 692
 <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>
641 693
   <span style="color: #93a8c6;">(</span>alexandria:once-only <span style="color: #b0b1a3;">(</span>app<span style="color: #b0b1a3;">)</span>
642 694
     `<span style="color: #b0b1a3;">(</span>setf
... ...
@@ -645,9 +697,11 @@ T
645 697
                            append `<span style="color: #b0b0b3;">(</span><span style="color: #90a890;">(</span>ningle:route ,app ,target
646 698
                                                   <span style="font-weight: bold;">:method</span> method<span style="color: #90a890;">)</span>
647 699
                                     ,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>
700
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">defroutes ends here</span>
648 701
 
702
+<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>
649 703
 <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>
650
-  <span style="color: #93a8c6;">(</span>list 200 nil value<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
704
+  <span style="color: #93a8c6;">(</span>list 200 '<span style="color: #b0b1a3;">(</span><span style="font-weight: bold;">:conent-type</span> <span style="color: #D0BF8F;">"application/json"</span><span style="color: #b0b1a3;">)</span> value<span style="color: #93a8c6;">)</span><span style="color: #8c8c8c;">)</span>
651 705
 
652 706
 <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>
653 707
   `<span style="color: #93a8c6;">(</span><span style="color: #F0DFAF;">lambda</span> <span style="color: #b0b1a3;">(</span>,sym<span style="color: #b0b1a3;">)</span>
... ...
@@ -657,6 +711,7 @@ T
657 711
        <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 712
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing-helpers ends here</span>
659 713
 
714
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">[[file:~/git_repos/lisp-sandbox/todo/README.org::todo-routes][todo-routes]]</span>
660 715
 <span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">routing</span>
661 716
 <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>
662 717
   <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>
... ...
@@ -673,13 +728,14 @@ T
673 728
                  <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 729
                             <span style="color: #b0b0b3;">(</span>update-todo <span style="color: #90a890;">(</span>get-id v<span style="color: #90a890;">)</span> 
675 730
                                          <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>
731
+<span style="color: #A6A689; background-color: #2B2B2B;">;; </span><span style="color: #A6A689; background-color: #2B2B2B;">todo-routes ends here</span>
676 732
 </pre>
677 733
 </div>
678 734
 </div>
679 735
 </div>
680 736
 
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>
737
+<div id="outline-container-org04fe926" class="outline-3">
738
+<h3 id="org04fe926"><span class="section-number-3">4.3</span> main.lisp source</h3>
683 739
 <div class="outline-text-3" id="text-4-3">
684 740
 <div class="org-src-container">
685 741
 <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>
... ...
@@ -725,7 +781,7 @@ T
725 781
 </div>
726 782
 <div id="postamble" class="status">
727 783
 <p class="author">Author: Langley</p>
728
-<p class="date">Created: 2019-08-30 Fri 02:00</p>
784
+<p class="date">Created: 2019-08-30 Fri 02:15</p>
729 785
 <p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
730 786
 </div>
731 787
 </body>
... ...
@@ -4,7 +4,7 @@
4 4
 
5 5
 ;; package-include ends here
6 6
 
7
-;; [[file:~/git_repos/lisp-sandbox/todo/README.org::routing-helpers][routing-helpers]]
7
+;; [[file:~/git_repos/lisp-sandbox/todo/README.org::defroutes][defroutes]]
8 8
 (defmacro defroutes (app &body routes)
9 9
   (alexandria:once-only (app)
10 10
     `(setf
... ...
@@ -13,9 +13,11 @@
13 13
                            append `((ningle:route ,app ,target
14 14
                                                   :method method)
15 15
                                     ,callback))))))
16
+;; defroutes ends here
16 17
 
18
+;; [[file:~/git_repos/lisp-sandbox/todo/README.org::routing-helpers][routing-helpers]]
17 19
 (defun success (value)
18
-  (list 200 nil value))
20
+  (list 200 '(:conent-type "application/json") value))
19 21
 
20 22
 (defmacro handler ((&optional (sym (gensym "PARAMS"))) &body body)
21 23
   `(lambda (,sym)
... ...
@@ -25,6 +27,7 @@
25 27
        (progn ,@body)))))
26 28
 ;; routing-helpers ends here
27 29
 
30
+;; [[file:~/git_repos/lisp-sandbox/todo/README.org::todo-routes][todo-routes]]
28 31
 ;; routing
29 32
 (defun get-id (params)
30 33
   (parse-integer (serapeum:assocdr :id params)))
... ...
@@ -41,4 +44,5 @@
41 44
                  (:PATCH  (handler (v)
42 45
                             (update-todo (get-id v) 
43 46
                                          (remove :id v :key #'car)))))))
47
+;; todo-routes ends here
44 48
 ;; routing.lisp source:1 ends here