diff options
Diffstat (limited to 'lazybones.lisp')
-rw-r--r-- | lazybones.lisp | 50 |
1 files changed, 18 insertions, 32 deletions
diff --git a/lazybones.lisp b/lazybones.lisp index c0f1550..03f6c70 100644 --- a/lazybones.lisp +++ b/lazybones.lisp @@ -114,6 +114,13 @@ app, named with the package name. If no app can be found, return NIL" :reader endpoint-route :initarg :route :initform (error "endpoint route required")) + (params + :reader endpoint-params + :initarg :params + :initform nil + :documentation "A list of (SYMBOL-NAME FUNCTION-SYMBOL), + documenting the query parameters this endpoint expects. Used for + generating both documentation and client functions.") (content-type :reader endpoint-content-type :initarg :content-type @@ -309,6 +316,7 @@ any way to do it, hence NIL is returned." (defmacro defendpoint (appname method route + query-params (&key (auth nil) content-type) @@ -322,12 +330,16 @@ making a new one if not." (a:with-gensyms (the-app auth-method) (let* ((dispatch-pattern (parse-route-string-template route)) - (params + (lambda-list (mapcar 'intern (route-variables dispatch-pattern))) (documentation (when (stringp (first body)) (first body))) + (body-without-docstring + (if (stringp (first body)) (rest body) body)) (real-body - (if (stringp (first body)) (rest body) body))) + (if query-params + `((map-parameters ,query-params ,@body-without-docstring)) + body-without-docstring))) `(let* ((,the-app (or (app ',appname) (make-instance 'lazybones:app :name ',appname))) (,auth-method @@ -338,52 +350,26 @@ making a new one if not." 'lazybones:endpoint :method ,method :route ,route + :params ',query-params :content-type ,content-type :pattern ',dispatch-pattern :doc ,documentation :auth ,auth-method :function - (lambda ,params + (lambda ,lambda-list (setf (lazybones:response-header :content-type) (or ,content-type (lazybones::default-content-type ,the-app))) ,@real-body))))))) -(defmacro defendpoint* (method route options &rest body) +(defmacro defendpoint* (method route params options &rest body) "Like DEFENDPOINT but uses the current package name as the app name." - `(defendpoint ,(default-app-name) ,method ,route ,options ,@body)) + `(defendpoint ,(default-app-name) ,method ,route ,params ,options ,@body)) ;;; ENDPOINT HANDLING UTILITIES -(defmacro let-parameters ((&rest names) &body body) - "NAMES is a list of symbols. Binds the names to the value of the -request parameters whose keys compare string-equal to the symbol-name -of each NAME, or NIL if there is no such parameter." - (let ((params (gensym))) - `(let ((,params (lazybones:request-parameters))) - (let ,(loop for name in names - for string-name = (symbol-name name) - collect `(,name (cdr (assoc ,string-name ,params :test #'string-equal)))) - ,@body)))) - -(defmacro map-parameters ((&rest params) &body body) - "PARAMS is a list of pairs (NAME PARSER). MAP-PARAMETERS behaves -exactly like LET-PARAMETERS except that the values boudn to NAMEs are -first mapped with the PARSER function." - (assert (loop for (name parser) in params - always (and (symbolp name) - (or (symbolp parser) (functionp parser)))) - () - "Malformed PARAMS in MAP-PARAMETERS macro") - - (let ((names (mapcar #'car params))) - `(let-parameters ,names - (let ,(loop for name in names - collect `(,name (when ,name (funcall ',(second (assoc name params)) ,name)))) - ,@body)))) - (defun http-ok (content) "Content should be a string, a byte-vector, or a pathname to a local |