From 6765a2c30ed66fd035337c57ec61210af6730779 Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Fri, 7 Jan 2022 00:49:36 +0000 Subject: [PATCH] Chapter 11 commit (Errors/Exceptions). This was hard to follow because the translation was quite bad. The gist of was use 'throw-code' for quick and basic relay of error (using HTTP response codes) and use 'on-exception' method to generate a more involved HTML page to communicate the error (HTTP response code). At least, I think that was the take-away. --- src/web.lisp | 84 +++++++++++++++++++++++++++++- templates/_errors/bad-request.html | 9 ++++ templates/_errors/not-found.html | 7 +++ templates/layouts/error.html | 26 +++++++++ 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 templates/_errors/bad-request.html create mode 100644 templates/_errors/not-found.html create mode 100644 templates/layouts/error.html diff --git a/src/web.lisp b/src/web.lisp index dfe4bcf..6518b42 100644 --- a/src/web.lisp +++ b/src/web.lisp @@ -27,7 +27,6 @@ ;; ;; Routing rules - (defroute "/" () "Top page" (let ((articless (articles-make 5))) @@ -38,7 +37,7 @@ ,@(roles) :token ,(token) :alert ,(flash-gethash :alert ningle:*session*) - ;; :news ,articles + :news ,articless :blogs (1 2 3 4 5) :articles ,articless)))) @@ -1166,3 +1165,84 @@ nil "/users/~D"(mito:object-id user)))))))) (:or (:= "public" :status) (:= "member-only" :status))))))) (sxql:order-by (:desc :date-posted)) (when limit (sxql:limit limit))))) + +;;; ------------------------------------------------------------------------- +;;; Custom Error Pages + +;;; 'throw-code' seems to be the most convenient way to generate an +;;; error page. But, it does not lend itself to generating a more +;;; involved error page like the 'on-exception' defmethod's do. + +;;; (throw-code 405 :allow "put get" :method "post")) + +(defroute "/error-test" () + ;; Change the error code (I.E. 405) to test different errors. + (throw-code 405 :allow "put get" :method "post")) + + +(defmethod on-exception ((app ) (code method-not-allowed)) + (setf (getf (lack.response:response-headers ningle:*response*):allow) + (allow code)) + (format nil "Unknown method ~S" (not-allowed code))) + +(defmethod on-exception ((app ) (code method-not-allowed)) + `(,(caveman2.exception:exception-code code) + (:allow ,(allow code)) + (,(format nil "Unknown method ~S" (not-allowed code))))) + +;;; The original 'on-exception' 404 error is higher up this file. +(defmethod on-exception ((app ) (code (eql 404))) + (declare (ignore app)) + (render "_errors/not-found.html")) ; You can adjust the '404 page'. + +;;; Here is a commented-out copy of it for quick reference. +;; (defmethod on-exception ((app ) (code (eql 404))) +;; (declare (ignore app)) +;; (merge-pathnames #P"_errors/404.html" +;; *template-directory*)) + +#| I DO NOT KNOW WHAT 'STATUS-CODE:+BAD-REQUEST+' IS REFERRING TO +====================================================================== + +This method is taken directly from Chapter 11. The 'status-code' part +is not recognised which means I cannot compile the program (or use +quickload). Because of this I have commented it out so I can keep it +as a reference and hopefully work out where '+bad-request+' resides so +I can import it and get this piece of code working. + +(defmethod on-exception ((app ) + (code (eql status-code:+bad-request+))) + (declare (ignore app)) + (render "errors/bad-request.html" + `(:alert ,(flash-gethash :alert ningle:*session*)))) +|# + +#| Added in Chapter 11 (Errors) +====================================================================== +Below, I think, is examples of how to form more complicated error +messages/pages/exceptions beyond what is provided by Caveman. I cannot +say for certain because the chapter's text is a bit hard to +read (Chapter 11). Google's Japanese to English translation is the +worse of all the chapters I have read up to now. +|# +(define-condition method-not-allowed (caveman2.exception:http-exception) + ((allow + :initarg :allow + :reader allow) + (method + :initarg :method + :reader not-allowed))) + +;;; -------------------------------------------------------------------- +;;; Code examples for using 'define-condition' above. +;;; These code snippets are taken directly from Chapter 11. + +#| +(let ((caveman2.exception:*exception-class* + 'method-not-allowed)) + (throw-code 405 :allow "put get" :method "post")) + +(error 'method-not-allowed :method "post" :allow "put get" :code 405) + +`(405 (:allow "put get")(,(format nil "Unknown method ~S""post"))) +|# diff --git a/templates/_errors/bad-request.html b/templates/_errors/bad-request.html new file mode 100644 index 0000000..2ace146 --- /dev/null +++ b/templates/_errors/bad-request.html @@ -0,0 +1,9 @@ +{% extends "layouts/error.html" %} +{% block title %}{% lisp (title! "Bad Request") %}{% endblock %} + +{% block main %} +

400 {% lisp (title!) %}

+{% if alert %} +

{{alert}}

+{% endif %} +{% endblock %} diff --git a/templates/_errors/not-found.html b/templates/_errors/not-found.html new file mode 100644 index 0000000..bc7dea0 --- /dev/null +++ b/templates/_errors/not-found.html @@ -0,0 +1,7 @@ +{% extends "layouts/error.html" %} + +{% block title %} {% lisp (title! "Not Found") %} {% endblock %} + +{% block main %} +

404 Not Found

+{% endblock %} diff --git a/templates/layouts/error.html b/templates/layouts/error.html new file mode 100644 index 0000000..8777775 --- /dev/null +++ b/templates/layouts/error.html @@ -0,0 +1,26 @@ + + + + + + {% block title %}Title{% endblock %} + + + + +
+
+ Image alt text + +
+
+ {% block main %}Main content here{% endblock %} +
+ +
+ +