[racket] Racket Web Server
From: pablo (r at uzy.me)
Date: Sun Dec 11 18:49:31 EST 2011 |
|
Hello,
On Sun, Dec 11, 2011 at 11:25 PM, Gerry Weaver <gerryw at compvia.com> wrote:
> Hello All,
>
> I am new to Racket and Lisp/Scheme in general. I am trying to write a simple
> rest web service in Racket, but I'm not making much progress. Unfortunately,
> I don't find the Racket docs to be very helpful. I guess my brain just isn't
> wired right ;-) Asking questions on the mailing list would almost be a step
> by step at this point, so I thought I would spare y'all from that. Anyway,
> I'm trying to find some alternative docs or examples. I had the same problem
> with the Sedna XML stuff, but once I found the scheme docs on Sedna's web
> site I was able to get going. I've been searching the web for some
> docs/examples, but no luck so far. Is there anything out there that would
> help?
>
I had a similar need recently, I developed a little library to use with
Racket's web-server. There's still no documentation, so I didn't put it
on PLaneT yet, but a few explanations might be enough. Don't hesitate to
ask further questions.
You can find the repaus.rkt file here: https://gitorious.org/repaus
In a racket module, you require "repaus.rkt" and then you have three new
form you can use :
- define-resource
- route
- serve
* define-resource allows you to define a… resource! It works like this:
(define-resource (name path-elements ...)
(http-method => procedure)
...)
- name is the name of the resource.
- path-elements are the request path separated by '/'. They can be
strings or symbols. Strings enforce the value and symbols are
"arguments". Symbols in path-elements can be preceded by #:number or
#:symbol to be converted automatically (to a number or a symbol
instead of a string). It can ends with ". some-symbol" to get a list
of all the remaining path-elemnts.
- http-method can be one of get, post, put, delete, patch, head.
- procedure must be a function which takes the request as first
argument, and then as many arguments as there are symbols in the
path-elements. Also, it must returns someting the web-server can use
as a response.
Examples:
(define-resource (home "")
;; /
(get => (lambda (req) #;"the home page")))
(define-resource (posts "posts")
;; /posts
(get => (lambda (req) #;"the n lasts posts"))
(post => (lambda (req) #;"creates a new post")))
; see the very good Racket web-server/http docs for how to get
; POST data and stuff from the request object.
(define-resource (post "posts" slug)
;; /posts/your-awesome-post, /posts/foo-bar, ...
(get => (lambda (req slug) #;"the slug post"))
(put => (lambda (req slug) #;"update the slug post"))
(delete => (lamdba (req slug) #;"delete the slug post")))
(define-resource (comments "posts" slug "comments")
;; /posts/foo-bar/comments, /posts/lalala/comments, ...
(get => (lambda (req slug) #;"comments for slug"))
(post => (lambda (req slug) #;"creates a comment for post slug")))
(define-resource (comment "posts" slug "comments" #:number id)
;; /posts/foo-bar/comments/42
(put => (lambda (req slug id) #;"edit comment id"))
(delete => (lambda (req slug id) #;"delete comment id")))
; here the id argument of the procedure is a number, I think for
; now it just breaks if Racket can't convert it to a number…
; (for instance /posts/foo-bar/comments/lala)
(define-resource (archives "archives" #:number year #:number month)
;; now it should be clear)
End examples.
Of course you can (should) define the procedure in other modules that
you require and just do stuff like "(get => show-posts)".
* route will takes some resources defined with define-resource as
arguments and make a functions which does the right dispatching that you
can use with serve:
(define blog (route home posts post comments comment archives))
* serve is just an alias to serve/servlet from Racket's
web-server/servlet (so you don't need to require it):
(serve blog
#:port 8080
#:listen-ip #f
#:servlet-regexp #rx""
#:stateless? #t
#:command-line? #t)
* Other details:
- OPTIONS request are automatically handled for existing resources.
- an empty response with a 404 (Not Found) status is sent if no
resources given to route match the request.
- an empty resources with a 405 (Method Not Allowed) status is sent if
the resource exists but the method is not defined.
Now, be aware that this is not quite polished as I wish it to be before
really giving it to the public: it still needs some documentation, the
default 404 and 405 response should be customizable, and to be a bit
more robust for the string->number conversion.
"I'll do that when I have some time…™"
Cheers :-).
--
Pablo.
http://pablo.rauzy.name/