Sunday, July 18, 2010

As shown before, you can create a web API by creating an SHP script as follows:

;; /api/add2
(:api-args (a number?) (b number?))
(+ a b)

Where both a and b are validated as number?. It would be nice if we can validate any type of scheme values, as long as the value can be created via the request input.

For example - let's say that you have a struct with the following definition:

(define-struct foo (bar baz))

We want to do the following:

(:api-args (foo foo?)) ;; takes in the foo struct

And let web API handle the rest. This is achieved via converters.

Converters

The mappings between the request and the api args are done via converters, which maps the parameter key against the type's test function (such as number?). And when you want to use the converter in the api-args expression, you specify the <test?> function in the parameter position in one of the following forms:

As usual, SHP comes with a small example site that you can play with under the example sub directory - cd to the example directory and run (require "web.ss") will start the example site. The example site is still just trivial code right now - it will eventually be enhanced and separated into its own package.

Cached Compiled Script

All of the scripts are now compiled and cached. This has some potential performance benefit, since we will only access the file content when the file timestamp changes (meaning the file has been touched and/or modified). As this is a non-visible feature, we won't spend much time discussing it, except to note that the change is not just done for performance reasons - it is also done to enable and simplify the design of web api, which is discussed below.

Web API

Under the example site you can find the script shp/api/add2, which contains the following:

;; -*- scheme -*- -p
(:api-args (a number?) (b number?))
(+ a b)

This is the new *web api* - it takes in 2 numbers, a and b, and return the added result. To write an api script, you must use the :api-args expression, and then supply the arguments inside. The arguments can be specified in the following forms:

(:api-args a b) ;; both a & b are non-validating and you get what's passed in
(:api-args (a number?) (b string?)) ;; a expects a number, and b expects a string
(:api-args (a number? 3) (b number? 5)) ;; a & b both expect numbers, and both have default values if they are not passed in (a defaults to 3, and b defaults to 5).

When you run the example site you can access the api via the following http call:

GET /api/add2 HTTP/1.0

When running the above in browser you should get back an XMLRPC response: