aboutsummaryrefslogtreecommitdiff
path: root/lazybones.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lazybones.lisp')
-rw-r--r--lazybones.lisp50
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