Improve routing, add helpers
This commit is contained in:
parent
63d7932890
commit
96e7dadfdf
14 changed files with 135 additions and 123 deletions
|
@ -21,7 +21,7 @@
|
|||
("ningle-fbr" .
|
||||
(:class qlot/source/git:source-git
|
||||
:initargs (:remote-url "https://github.com/skyizwhite/ningle-fbr.git")
|
||||
:version "git-3c83e74a84e57f8ee2a9e98c4045d9b3e7a937f5"))
|
||||
:version "git-19aae06f7ff17f16f008133a3bf234b89ab7de1e"))
|
||||
("lack-mw" .
|
||||
(:class qlot/source/git:source-git
|
||||
:initargs (:remote-url "https://github.com/skyizwhite/lack-mw.git")
|
||||
|
|
9
src/api/not-found.lisp
Normal file
9
src/api/not-found.lisp
Normal file
|
@ -0,0 +1,9 @@
|
|||
(defpackage #:website/api/not-found
|
||||
(:use #:cl
|
||||
#:jingle)
|
||||
(:export #:handle-not-found))
|
||||
(in-package #:website/api/not-found)
|
||||
|
||||
(defun handle-not-found ()
|
||||
(set-response-status :not-found)
|
||||
'(:|message| "Not found"))
|
|
@ -1,17 +1,17 @@
|
|||
(defpackage #:website/routes/api/revalidate
|
||||
(defpackage #:website/api/revalidate
|
||||
(:use #:cl
|
||||
#:jingle
|
||||
#:access)
|
||||
(:import-from #:website/lib/env
|
||||
#:microcms-webhook-key)
|
||||
(:import-from #:website/helper
|
||||
#:get-request-body-plist)
|
||||
#:request-body-json->plist)
|
||||
(:import-from #:website/lib/cms
|
||||
#:clear-about-cache
|
||||
#:clear-works-cache
|
||||
#:clear-blog-cache)
|
||||
(:export #:handle-post))
|
||||
(in-package #:website/routes/api/revalidate)
|
||||
(in-package #:website/api/revalidate)
|
||||
|
||||
(defun handle-post (params)
|
||||
(declare (ignore params))
|
||||
|
@ -19,7 +19,7 @@
|
|||
(microcms-webhook-key))
|
||||
(set-response-status :unauthorized)
|
||||
(return-from handle-post '(:|message| "Invalid token")))
|
||||
(let* ((body (get-request-body-plist))
|
||||
(let* ((body (request-body-json->plist))
|
||||
(api (getf body :|api|))
|
||||
(id (getf body :|id|))
|
||||
(old-draft-key (accesses body :|contents| :|old| :|draftKey|))
|
66
src/app.lisp
66
src/app.lisp
|
@ -1,27 +1,71 @@
|
|||
(defpackage #:website/app
|
||||
(:use #:cl
|
||||
#:jingle)
|
||||
#:jingle
|
||||
#:hsx)
|
||||
(:import-from #:jonathan
|
||||
#:to-json)
|
||||
(:import-from #:ningle-fbr
|
||||
#:set-routes)
|
||||
(:import-from #:lack/middleware/mount
|
||||
#:*lack-middleware-mount*)
|
||||
(:import-from #:lack-mw
|
||||
#:*trim-trailing-slash*)
|
||||
(:import-from #:clack-errors
|
||||
#:*clack-error-middleware*)
|
||||
(:import-from #:website/components/metadata
|
||||
#:~metadata)
|
||||
(:import-from #:website/components/scripts
|
||||
#:~scripts)
|
||||
(:import-from #:website/components/layout
|
||||
#:~layout)
|
||||
(:import-from #:website/lib/env
|
||||
#:dev-mode-p)
|
||||
(:import-from #:website/renderer)
|
||||
(:export #:*app*))
|
||||
(in-package #:website/app)
|
||||
|
||||
(defparameter *page-app* (make-app))
|
||||
(set-routes *page-app* :system :website :target-dir-path "pages")
|
||||
|
||||
(defmethod jingle:process-response :around ((app (eql *page-app*)) result)
|
||||
(set-response-header :content-type "text/html; charset=utf-8")
|
||||
(when (eq (request-method *request*) :get)
|
||||
(let ((strategy (context :cache)))
|
||||
(cond ((dev-mode-p)
|
||||
(set-response-header :cache-control "private, no-store, must-revalidate"))
|
||||
((eq strategy :ssr)
|
||||
(set-response-header :cache-control "public, max-age=0, must-revalidate"))
|
||||
((eq strategy :isr)
|
||||
(set-response-header :cache-control "public, max-age=0, s-maxage=60, stale-while-revalidate=60"))
|
||||
((eq strategy :sg)
|
||||
(set-response-header :cache-control "public, max-age=0, s-maxage=31536000, must-revalidate")))))
|
||||
(call-next-method app
|
||||
(render-to-string
|
||||
(hsx (html :lang "en"
|
||||
(head
|
||||
(~metadata :metadata (context :metadata))
|
||||
(~scripts))
|
||||
(body
|
||||
(~layout result)))))))
|
||||
|
||||
(defparameter *api-app* (make-app))
|
||||
(set-routes *api-app* :system :website :target-dir-path "api")
|
||||
|
||||
(defmethod jingle:process-response :around ((app (eql *api-app*)) result)
|
||||
(set-response-header :content-type "application/json; charset=utf-8")
|
||||
(call-next-method app (to-json result)))
|
||||
|
||||
(defun with-args (middleware &rest args)
|
||||
(lambda (app)
|
||||
(apply middleware app args)))
|
||||
|
||||
(defparameter *app*
|
||||
(let ((app (make-app)))
|
||||
(set-routes app :system :website :target-dir-path "routes")
|
||||
(install-middleware app (lambda (app)
|
||||
(funcall *clack-error-middleware*
|
||||
app
|
||||
:debug (dev-mode-p))))
|
||||
(install-middleware app *trim-trailing-slash*)
|
||||
(static-path app "/assets/" "assets/")
|
||||
(configure app)))
|
||||
(progn
|
||||
(install-middleware *page-app*
|
||||
(with-args *lack-middleware-mount* "/api" *api-app*))
|
||||
(install-middleware *page-app*
|
||||
(with-args *clack-error-middleware* :debug (dev-mode-p)))
|
||||
(install-middleware *page-app* *trim-trailing-slash*)
|
||||
(static-path *page-app* "/assets/" "assets/")
|
||||
(configure *page-app*)))
|
||||
|
||||
*app*
|
||||
|
|
|
@ -5,18 +5,12 @@
|
|||
#:make-flexi-stream)
|
||||
(:import-from #:jonathan
|
||||
#:parse)
|
||||
(:export #:api-request-p
|
||||
#:get-request-body-plist))
|
||||
(:export #:request-body-json->plist
|
||||
#:set-metadata
|
||||
#:set-cache))
|
||||
(in-package #:website/helper)
|
||||
|
||||
(defun starts-with-p (prefix string)
|
||||
(let ((pos (search prefix string :start1 0 :end1 (length prefix) :start2 0)))
|
||||
(and pos (= pos 0))))
|
||||
|
||||
(defun api-request-p ()
|
||||
(starts-with-p "/api/" (request-uri *request*)))
|
||||
|
||||
(defun get-request-body-plist ()
|
||||
(defun request-body-json->plist ()
|
||||
(parse
|
||||
(let ((text-stream (make-flexi-stream (request-raw-body *request*)
|
||||
:external-format :utf-8)))
|
||||
|
@ -24,3 +18,9 @@
|
|||
(loop :for char := (read-char text-stream nil)
|
||||
:while char
|
||||
:do (write-char char out))))))
|
||||
|
||||
(defun set-metadata (metadata)
|
||||
(setf (context :metadata) metadata))
|
||||
|
||||
(defun set-cache (strategy)
|
||||
(setf (context :cache) strategy))
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
(defpackage #:website/routes/about
|
||||
(defpackage #:website/pages/about
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle)
|
||||
#:jingle
|
||||
#:website/helper)
|
||||
(:import-from #:website/lib/cms
|
||||
#:fetch-about)
|
||||
(:import-from #:website/components/article
|
||||
#:~article)
|
||||
(:export #:handle-get))
|
||||
(in-package #:website/routes/about)
|
||||
(in-package #:website/pages/about)
|
||||
|
||||
(defparameter *metadata*
|
||||
(list :title "about"))
|
||||
|
||||
(defun handle-get (params)
|
||||
(setf (context :metadata) *metadata*)
|
||||
(set-metadata *metadata*)
|
||||
(with-request-params ((draft-key "draft-key" nil)) params
|
||||
(setf (context :cache) (if draft-key :ssr :isr))
|
||||
(set-cache (if draft-key :ssr :isr))
|
||||
(let ((about (fetch-about :draft-key draft-key)))
|
||||
(~article
|
||||
:title "About"
|
|
@ -1,15 +1,16 @@
|
|||
(defpackage #:website/routes/blog/<id>
|
||||
(defpackage #:website/pages/blog/<id>
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle)
|
||||
#:jingle
|
||||
#:website/helper)
|
||||
(:import-from #:website/lib/cms
|
||||
#:fetch-blog-detail)
|
||||
(:import-from #:website/routes/not-found
|
||||
(:import-from #:website/pages/not-found
|
||||
#:handle-not-found)
|
||||
(:import-from #:website/components/article
|
||||
#:~article)
|
||||
(:export #:handle-get))
|
||||
(in-package #:website/routes/blog/<id>)
|
||||
(in-package #:website/pages/blog/<id>)
|
||||
|
||||
(defun handle-get (params)
|
||||
(with-request-params ((id :id nil)
|
||||
|
@ -17,10 +18,10 @@
|
|||
(let ((blog (fetch-blog-detail id :draft-key draft-key)))
|
||||
(unless blog
|
||||
(return-from handle-get (handle-not-found)))
|
||||
(setf (context :cache) (if draft-key :ssr :isr))
|
||||
(setf (context :metadata) (list :title (getf blog :title)
|
||||
:description (getf blog :description)
|
||||
:type "article"))
|
||||
(set-cache (if draft-key :ssr :isr))
|
||||
(set-metadata (list :title (getf blog :title)
|
||||
:description (getf blog :description)
|
||||
:type "article"))
|
||||
(hsx
|
||||
(~article
|
||||
:title (getf blog :title)
|
|
@ -1,21 +1,22 @@
|
|||
(defpackage #:website/routes/blog/index
|
||||
(defpackage #:website/pages/blog/index
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle)
|
||||
#:jingle
|
||||
#:website/helper)
|
||||
(:import-from #:website/lib/cms
|
||||
#:fetch-blog-list)
|
||||
(:import-from #:website/lib/time
|
||||
#:asctime)
|
||||
(:export #:handle-get))
|
||||
(in-package #:website/routes/blog/index)
|
||||
(in-package #:website/pages/blog/index)
|
||||
|
||||
(defparameter *metadata*
|
||||
(list :title "blog"))
|
||||
|
||||
(defun handle-get (params)
|
||||
(declare (ignore params))
|
||||
(setf (context :cache) :isr)
|
||||
(setf (context :metadata) *metadata*)
|
||||
(set-cache :isr)
|
||||
(set-metadata *metadata*)
|
||||
(let ((blogs (fetch-blog-list :page 1)))
|
||||
(hsx
|
||||
(section
|
|
@ -1,13 +1,14 @@
|
|||
(defpackage #:website/routes/index
|
||||
(defpackage #:website/pages/index
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:access
|
||||
#:jingle)
|
||||
#:jingle
|
||||
#:website/helper)
|
||||
(:import-from #:website/lib/cms
|
||||
#:get-about)
|
||||
(:export #:handle-get
|
||||
#:handle-head))
|
||||
(in-package #:website/routes/index)
|
||||
(in-package #:website/pages/index)
|
||||
|
||||
(defparameter *links*
|
||||
'(("Keyoxide"
|
||||
|
@ -28,7 +29,7 @@
|
|||
|
||||
(defun handle-get (params)
|
||||
(declare (ignore params))
|
||||
(setf (context :cache) :sg)
|
||||
(set-cache :sg)
|
||||
(hsx
|
||||
(div :class "flex flex-col items-center justify-center h-full"
|
||||
(img
|
23
src/pages/not-found.lisp
Normal file
23
src/pages/not-found.lisp
Normal file
|
@ -0,0 +1,23 @@
|
|||
(defpackage #:website/pages/not-found
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle
|
||||
#:website/helper)
|
||||
(:export #:handle-not-found))
|
||||
(in-package #:website/pages/not-found)
|
||||
|
||||
(defparameter *metadata*
|
||||
'(:title "404 Not Found"
|
||||
:description "The page you are looking for may have been deleted or the URL might be incorrect."
|
||||
:error t))
|
||||
|
||||
(defun handle-not-found ()
|
||||
(set-response-status :not-found)
|
||||
(set-cache :ssr)
|
||||
(set-metadata *metadata*)
|
||||
(hsx
|
||||
(div :class "flex flex-col h-full items-center justify-center gap-y-6"
|
||||
(h1 :class "font-bold text-2xl"
|
||||
"404 Not Found")
|
||||
(a :href "/" :class "text-lg text-pink-500 hover:underline"
|
||||
"Back to TOP"))))
|
|
@ -1,21 +1,22 @@
|
|||
(defpackage #:website/routes/works
|
||||
(defpackage #:website/pages/works
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle)
|
||||
#:jingle
|
||||
#:website/helper)
|
||||
(:import-from #:website/lib/cms
|
||||
#:fetch-works)
|
||||
(:import-from #:website/components/article
|
||||
#:~article)
|
||||
(:export #:handle-get))
|
||||
(in-package #:website/routes/works)
|
||||
(in-package #:website/pages/works)
|
||||
|
||||
(defparameter *metadata*
|
||||
(list :title "works"))
|
||||
|
||||
(defun handle-get (params)
|
||||
(setf (context :metadata) *metadata*)
|
||||
(set-metadata *metadata*)
|
||||
(with-request-params ((draft-key "draft-key" nil)) params
|
||||
(setf (context :cache) (if draft-key :ssr :isr))
|
||||
(set-cache (if draft-key :ssr :isr))
|
||||
(let ((works (fetch-works :draft-key draft-key)))
|
||||
(~article
|
||||
:title "Works"
|
|
@ -1,42 +0,0 @@
|
|||
(defpackage #:website/renderer
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle)
|
||||
(:import-from #:jonathan
|
||||
#:to-json)
|
||||
(:import-from #:website/lib/env
|
||||
#:dev-mode-p)
|
||||
(:import-from #:website/helper
|
||||
#:api-request-p)
|
||||
(:import-from #:website/components/metadata
|
||||
#:~metadata)
|
||||
(:import-from #:website/components/scripts
|
||||
#:~scripts)
|
||||
(:import-from #:website/components/layout
|
||||
#:~layout))
|
||||
(in-package #:website/renderer)
|
||||
|
||||
(defmethod jingle:process-response :around ((app jingle:app) result)
|
||||
(when (eq (request-method *request*) :get)
|
||||
(let ((strategy (context :cache)))
|
||||
(cond ((dev-mode-p)
|
||||
(set-response-header :cache-control "private, no-store, must-revalidate"))
|
||||
((eq strategy :ssr)
|
||||
(set-response-header :cache-control "public, max-age=0, must-revalidate"))
|
||||
((eq strategy :isr)
|
||||
(set-response-header :cache-control "public, max-age=0, s-maxage=60, stale-while-revalidate=60"))
|
||||
((eq strategy :sg)
|
||||
(set-response-header :cache-control "public, max-age=0, s-maxage=31536000, must-revalidate")))))
|
||||
(cond ((api-request-p)
|
||||
(set-response-header :content-type "application/json; charset=utf-8")
|
||||
(call-next-method app (to-json result)))
|
||||
(t
|
||||
(set-response-header :content-type "text/html; charset=utf-8")
|
||||
(call-next-method app
|
||||
(render-to-string
|
||||
(hsx (html :lang "en"
|
||||
(head
|
||||
(~metadata :metadata (context :metadata))
|
||||
(~scripts))
|
||||
(body
|
||||
(~layout result)))))))))
|
|
@ -1,26 +0,0 @@
|
|||
(defpackage #:website/routes/not-found
|
||||
(:use #:cl
|
||||
#:hsx
|
||||
#:jingle)
|
||||
(:import-from #:website/helper
|
||||
#:api-request-p)
|
||||
(:export #:handle-not-found))
|
||||
(in-package #:website/routes/not-found)
|
||||
|
||||
(defparameter *metadata*
|
||||
'(:title "404 Not Found"
|
||||
:description "The page you are looking for may have been deleted or the URL might be incorrect."
|
||||
:error t))
|
||||
|
||||
(defun handle-not-found ()
|
||||
(set-response-status :not-found)
|
||||
(setf (context :cache) :ssr)
|
||||
(setf (context :metadata) *metadata*)
|
||||
(if (api-request-p)
|
||||
'(:|message| "404 Not Found")
|
||||
(hsx
|
||||
(div :class "flex flex-col h-full items-center justify-center gap-y-6"
|
||||
(h1 :class "font-bold text-2xl"
|
||||
"404 Not Found")
|
||||
(a :href "/" :class "text-lg text-pink-500 hover:underline"
|
||||
"Back to TOP")))))
|
|
@ -1,8 +1,7 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/renderer.lisp",
|
||||
"./src/routes/**/*.lisp",
|
||||
"./src/pages/**/*.lisp",
|
||||
"./src/components/**/*.lisp",
|
||||
],
|
||||
theme: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue