From 49f8cafff4b63ebb7c0fa3bfc182072d8d5197ea Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 13 Feb 2022 19:38:51 -0600 Subject: Made 200 response the default. http-err now singals condition --- example/lazybones-example.lisp | 21 +++++++++------------ lazybones-hunchentoot.lisp | 9 +++++++-- lazybones.asd | 2 +- lazybones.lisp | 22 +++++++++------------- package.lisp | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/example/lazybones-example.lisp b/example/lazybones-example.lisp index 1efc882..88a58a1 100644 --- a/example/lazybones-example.lisp +++ b/example/lazybones-example.lisp @@ -5,7 +5,6 @@ (:local-nicknames (#:lzb #:lazybones)) (:import-from #:lazybones #:defendpoint* - #:http-ok #:http-err)) (in-package :lazybones-example) @@ -60,21 +59,21 @@ to 'coolsessionbro'." (print (lzb:request-body)) ; dummy implementation, prints post body to stdout (setf (lzb:response-cookie "testappsession") "coolsessionbro") - (http-ok "true")) + "true") ;; The next route defines a route variable WHO (defendpoint* :get "/hello/:who:" () () "Echos back Hello WHO" - (http-ok (format nil "Hello ~a~%" who))) ; use the route variable here + (format nil "Hello ~a~%" who)) ; use the route variable here (defendpoint* :post "/hello/:who:" () (:auth t) ; use the app's default authorizor "Echo's back 'Hello WHO, I got your message BODY' where BODY is the post body." (print (lzb:request-header :content-type)) (let ((body (lzb:request-body))) - (http-ok (format nil "Hello ~a, I got your message ~a~%" - who body)))) + (format nil "Hello ~a, I got your message ~a~%" + who body))) ;; Some helpers, these are used to parse url variables and query ;; parameters. Their docstrings are used in the API documentation @@ -92,7 +91,7 @@ ;; a 500 error will be returned. The syntax is (VAR PARSER) (defendpoint* :get "/search" ((name str) (age int)) () "Echo the search parameters in a nice list." - (http-ok (format nil "Name: ~a~%age: ~a~%" name age))) + (format nil "Name: ~a~%age: ~a~%" name age)) (defun crapshoot-authorizer () "Randomly decides that the request is authorized" @@ -101,16 +100,15 @@ (defendpoint* :post "/crapshoot" () (:auth 'crapshoot-authorizer) ; use a custom authorizer "Echos back 'You made it' if the request was authorized" - (http-ok "You made it")) + "You made it") ;; Route variables can accept parsers / preformatters ;; these will parse a value and supply it to the argument of the handler. (defendpoint* :get "/random/:lo int:/:hi int:" () () "Echo back a random number between lo and hi" (if (< lo hi) - (http-ok - (format nil "The number is: ~a~%" - (+ lo (random (- hi lo))))) + (format nil "The number is: ~a~%" + (+ lo (random (- hi lo)))) (http-err 404))) ; Can't find a number X such that LO >= HI and LO < X < HI (defun person-by-id (id) @@ -124,6 +122,5 @@ (defendpoint* :get "/person/:person person-by-id:" () (:content-type "application/json") ; override the app's default content type for HTTP responses "Returns a json representation of the person." - (http-ok - (jonathan:to-json person))) + (jonathan:to-json person)) diff --git a/lazybones-hunchentoot.lisp b/lazybones-hunchentoot.lisp index b010052..c5e55fa 100644 --- a/lazybones-hunchentoot.lisp +++ b/lazybones-hunchentoot.lisp @@ -39,11 +39,16 @@ finally (let ((lzb:*request* request) (lzb:*response* h:*reply*)) (return (lzb:http-err 404)))) + (lzb::http-error (http-error) + (let ((lzb:*request* request) + (lzb:*response* h:*reply*)) + (with-slots (lzb::code lzb::content) http-error + (http-respond lzb::content lzb::code)))) (error (e) (declare (ignorable e)) (let ((lzb:*request* request) (lzb:*response* h:*reply*)) - (lzb:http-err 500))))) + (http-respond 500))))) ;;; SERVER FUNCTIONS @@ -220,7 +225,7 @@ the value of the Content-Type request header." (cadar (setf (h:cookies-out response) (cons (cons name value) (h:cookies-out response)))))) -(defun http-respond (code content) +(defun http-respond (content &optional (code 200)) "Final step preparing response before backend does the rest. For Hunchentoot, set the response code and a few headers. If content is a pathname, pass off to HUNCHENTOOT:HANDLE-STATIC-FILE, otherwise just diff --git a/lazybones.asd b/lazybones.asd index 415b2c1..367c7c2 100644 --- a/lazybones.asd +++ b/lazybones.asd @@ -4,7 +4,7 @@ :description "http route handling" :author "Colin Okay " :license "AGPLv3" - :version "0.3.0" + :version "0.4.0" :serial t :depends-on (#:alexandria #:str diff --git a/lazybones.lisp b/lazybones.lisp index bab6ca2..fe2ebc3 100644 --- a/lazybones.lisp +++ b/lazybones.lisp @@ -18,6 +18,13 @@ "Dynamic variable holding the an APP instance. Dynamically bound by RUN-ENDPOINT so that it is available if needed in request handlers.") +;;; HTTP-ERROR CONDITION + +(define-condition http-error (condition) + ((code :initarg :code) + (content :initarg :content))) + + ;;; APP NAMESPACE (lisp-namespace:define-namespace lazybones) @@ -365,21 +372,10 @@ making a new one if not." "Like DEFENDPOINT but uses the current package name as the app name." `(defendpoint ,(default-app-name) ,method ,route ,params ,options ,@body)) - - - ;;; ENDPOINT HANDLING UTILITIES - -(defun http-ok (content) - "Content should be a string, a byte-vector, or a pathname to a local -file. CONTENT-TYPE should be a MIME type string." - (http-respond 200 content)) - (defun http-err (code &optional content) - "*APP*, *RESPONSE* and *REQUEST* should all be defined here." - (http-respond - code - content)) + "Singals an HTTP-ERROR with code and content." + (signal 'http-error :content content :code code)) diff --git a/package.lisp b/package.lisp index 22766cd..35ef7ab 100644 --- a/package.lisp +++ b/package.lisp @@ -41,6 +41,7 @@ #:*app* #:*request* #:*response* + #:http-error #:generate-app-documentation #:provision-app #:app @@ -53,7 +54,6 @@ #:let-parameters #:map-parameters #:http-err - #:http-ok #:http-respond #:install-app #:request-body -- cgit v1.2.3