Anonymous committed eb629a8

Add support for APIs that have constant path-fragments after the arguments

For example, the Bitcoin API is of the form<currency>/money/ticker

...but rest-bind assumes that the arguments to the API call always come
last in the path of the URI.

Alaric jumps through some hoops to bind a version of the API in which he
can parameterize the currency.

We now support doing this with define-method by allowing constant path
components to appear literally as strings in the argument list.

Signed-off-by: Andy Bennett <>

Comments (0)

Files changed (2)

 	     (pred     (lambda (x) (not (eqv? '#!key x))))
 	     (params   (drop-while pred args))
 	     (params   (if (null? params) params (cdr params)))
-	     (pos-args (take-while pred args))
+	     (uri-args  (take-while pred args))
+	     (proc-args (fold (lambda (arg args)
+				(cond ((symbol? arg) (cons arg args))
+				      ((string? arg) args)
+				      (else (abort (conc "Cannot handle " arg)))))
+			      '() uri-args))
 	     (uri/req  (second defn))
 	     (writer   (third defn))
 	     (reader   (fourth defn))
 	     (header-reader (if (= 5 (length defn)) (fifth defn) #f))
-	     (args     (if writer
-			 `(,@pos-args body)
-			 `(,@pos-args)))
-	     (args     (if (not (null? params))
-			 `(,@args #!key ,@params)
-			 `(,@args))))
+	     (proc-args (if writer
+			  `(,@proc-args body)
+			  `(,@proc-args)))
+	     (proc-args (if (not (null? params))
+			  `(,@proc-args #!key ,@params)
+			  `(,@proc-args))))
 	;(list 'quote
 	      `(define ,name
 		 (let* ((writer  ,writer)
 			(method  (cond ((request? uri/req) (request-method uri/req))
 				       (writer 'POST)
 				       (else 'GET))))
-		   (lambda ,args
-		     (let* (,@(if (not (null? pos-args))
-			      `((uri (update-uri uri path: (append (uri-path uri) (map ->string (list ,@pos-args)))))
+		   (lambda ,proc-args
+		     (let* (,@(if (not (null? uri-args))
+			      `((uri (update-uri uri path: (append (uri-path uri) (map ->string (list ,@uri-args)))))
 				      ;(_ (pp (uri-path uri)))


 parameters given.
 Creates a procedure {{procedure-name}} that calls the HTTP API specified in
-{{uri-or-request}}. Arguments specified in {{path-arg}} are appended, in the
-other they appear, to the end of the URI, separated by /. These arguments are
-mandatory. Arguments specified in {{query-arg}} are optional and, if present
+Arguments specified in {{path-arg}} are appended, in the order they appear, to
+the end of the URI, separated by /. Arguments specified as symbols will be
+turned into mandatory positional arguments to the procedure {{procedure-name}}.
+These argument values will end up in the correct place in the API call when
+{{procedure-name}} is called. Arguments specified strings will be placed into
+the URL in the correct position as constants and cannot be changed during calls
+to {{procedure-name}}.
+Arguments specified in {{query-arg}} are optional and, if present
 are placed in the query string. They are named as they appear in the
 definition. Their value is that as given when {{procedure-name}} is called.
     (cut read-string #f <>))
+=== 3
+Here we bind to
+This "API" has an argument in the middle of the URL and the constant parts
+"money" and "ticker" follow.
+    (use rest-bind http-client medea)
+    (define-method (btc-ticker currency "money" "ticker")
+    ""
+    #f
+    read-json)
 === License