CRUD web APIs using the Racket web server
Writing sophisticated web services in Racket is possible, but upon reading the official documentation, you might not feel that way. The truth is that you can make modern CRUD (create, read, update, delete) HTTP APIs (by which I mean web applications that aren't necessarily generate HTML, to be accessed and handled by a web browser) straightforwardly, all using Racket's built-in web server. In this post I've got some starter code that should give you an idea of how this kind of web application can be written.
Before diving into the code, let's begin by describing, first, what our application is supposed to do. Imagine that we're dealing only with a part of a whole web application. Let's concentrate on just one bit, with the understanding that we can flesh out the application in other ways using code not given here.
Imagine a web service that handles a catalog that can be modified. The URLs look like this:
|A JSON rendering of the current catalog database|
|A string showing the current value (returning 404 if does not yet exist)|
|Unconditionally associate (possibly overwriting) a value|
|Unconditionally delete |
The idea is that we can fetch the whole catalog, and get a JSON object back. We can add items to and delete items from the catalog. Item identifiers are simply integers.
Some features are missing, such as authentication. But that's a whole other ball of wax.
Here's the code (let's call it
Things get going at the very bottom, with
dispatch-rules. There, we define the routes (URLs) that interest us. It closely parallels the table above.
One thing to notice at the very bottom of the module is the
#:servlet-regexp #rx"" that makes sure that
helpfully return a response that we do not explicitly handle. Notice that in the dispatch-rules we have a fallback clause that calls the
not-found function (which we define here) that simply generates a 404 response.
Another thing to notice how exceptions are used to make sure that we are really dealing with input that we know how to handle. The idea, specifically, is that we want an the
value of an item to be a UTF-8 string. But our input is a sequence of bytes. Many sequences of bytes are not valid UTF-8 strings, so we need to check that we're dealing with a legitimate byte string.
This code could be tightened up in certain respects. And, again, it is obviously but one piece of a larger site. But hopefully this is enough to give you a sense for how to get started with this kind of web programming in Racket.
Using the server
There are a couple ways to run the server: at the command line or with DrRacket.
To run the server on the command line, just do:
If you'd like to run the code in DrRacket, just open
crud.rkt there and hit Run. In the definitions are, you won't see any output, but the server is running. (Do you see the little DrRacket running man in the lower right corner?
How about testing our mini CRUD service? There are, again, many ways to do this. Here's a simple way to do it in the shell. Try:
curl -X PUT --data "hi there" http://127.0.0.1:6892/catalog/123
You should see no output. If you're curious, try adding --verbose to the
curl -X GET http://127.0.0.1:6892/catalog/123
Play around with other URLs using
curl or any other tool of your choose to get a feel for what this little server can do.