You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.2 KiB
103 lines
3.2 KiB
(in-package :cl-user) |
|
(defpackage rails-to-caveman.web |
|
(:use :cl |
|
:caveman2 |
|
:rails-to-caveman.config |
|
:rails-to-caveman.view |
|
:rails-to-caveman.db |
|
:datafly |
|
:sxql) |
|
(:export :*web*)) |
|
(in-package :rails-to-caveman.web) |
|
|
|
;; for @route annotation |
|
(syntax:use-syntax :annot) |
|
|
|
;; |
|
;; Application |
|
|
|
(defclass <web> (<app>) ()) |
|
(defvar *web* (make-instance '<web>)) |
|
(clear-routing-rules *web*) |
|
|
|
;; |
|
;; Routing rules |
|
|
|
(defroute "/" () |
|
(render #P"index.html")) |
|
|
|
(defroute "/about" () |
|
(render #P"about.html" '(:page-title "About"))) |
|
|
|
(defroute "/hello/:name" (&key name) |
|
;; Substitutes `:name' with `name'. |
|
(format nil "Hello, ~A" name)) |
|
|
|
(defroute "/say/*/to/*" (&key splat) |
|
;; If route is /say/hello/to/world (in the browser). It will match |
|
;; to /say/hello/to/world. 'hello' and 'world' are the wildcard |
|
;; values in this example. |
|
(format nil "~A" splat)) |
|
|
|
(defroute ("/hello/([\\w]+)" :regexp t) (&key captures) |
|
;; Parse the second part of the URL via a regular expression |
|
;; (regexp). The result of the parsed regexp text is stored in |
|
;; `captures', hence the use of 'first' in the format string. |
|
(format nil "Hello, ~A!" (first captures))) |
|
|
|
(defroute "/hello/?:name?" (&key name) |
|
;; Generates two types of routes: |
|
|
|
;; 1. /hello/earth |
|
;; 2. /hello?NAME=earth |
|
|
|
;; The query string must be in UPPERCASE. Otherwise, the `name' will |
|
;; be bound to `nil'. |
|
(format nil "Hello, ~A" name)) |
|
|
|
(defroute "/hello/?:name?" (&key |name|) |
|
;; If you want the query string in lowercase, enclose `name' (in |
|
;; this case) with vertical bars '|'. This will force you to have |
|
;; only one route (unlike the route above). `NAME' will now bind to |
|
;; `nil'. |
|
|
|
;; 1. /hello?name=earth |
|
;; 2. /hello?NAME=earth <--- no longer works ('earth' binds to nil). |
|
;; 3. /hello/earth <--- no longer works |
|
(format nil "Hello, ~A" |name|)) |
|
|
|
(defroute "/lesson/step*/:name" (&key splat name) |
|
;; Directory style: Working with Parameters. |
|
;; Example URL: /lesson/step1/Sato |
|
(case (parse-integer (car splat) :junk-allowed t) |
|
(1 (format nil "Hello, ~A" name)))) |
|
|
|
(defroute "/lesson/step*" (&key splat (|name| "Anonymous")) |
|
;; 'Anonymous' is the default value for `|name|'. |
|
;; Query style: Working with Parameters. |
|
;; Example URL: lesson/step1?name=Sato |
|
(case (parse-integer (car splat) :junk-allowed t) |
|
(1 (format nil "Hello, ~A" |name|)))) |
|
|
|
(defroute "/lesson/step*" (&key splat name) |
|
;; If /lesson/step1 is used, it will be redirected to /lesson/step2, |
|
;; then /lesson/step3 and finally /lesson/step4. No matter where you |
|
;; start (along as it is below 4), the redirects will always take |
|
;; you wot /lesson/step4. |
|
|
|
;; The example includes `name' but it is never used. I am keeping it |
|
;; here for consistency between the reference material and this code |
|
;; base. |
|
(case (parse-integer (car splat) :junk-allowed t) |
|
(1 '(302 (:location "/lesson/step2"))) |
|
(2 '(302 (:location "/lesson/step3"))) |
|
(3 '(302 (:location "/lesson/step4"))) |
|
(4 "Moved to step4"))) |
|
|
|
;; |
|
;; Error pages |
|
|
|
(defmethod on-exception ((app <web>) (code (eql 404))) |
|
(declare (ignore app)) |
|
(merge-pathnames #P"_errors/404.html" |
|
*template-directory*))
|
|
|