Static URL Routing#
Previous: Serving Dynamic Content
This example will show how URL routing works in the Dylan web server, and how to handle optional URL elements for your resources.
I will skip the library and module definitions since they’re essentially the same as in the previous examples, but they are included in the full code listing at the end.
In the Dylan web server, add-resource
maps a URL to a resource. The
default implementation of add-resource
builds up a tree structure whose
paths are defined by URL path elements and whose leaves are <resource>
objects. (Idea stolen from twisted.web.
I hope to add a simple regular expression based router in the future, for
comparison.)
For this example we’ll use a hypothetical wiki as our web application and add
three different URLs for it. First, we need a $wiki-app
resource that will
be the root of all wiki URLs, and specialized resource classes to provide
behavior. We’ll implement page, user and group resources for the wiki:
define constant $wiki-app = make(<resource>);
define class <page> (<resource>) end;
define class <user> (<resource>) end;
define class <group> (<resource>) end;
Now wiki resources can be added as children of $wiki-app
:
add-resource($wiki-app, "page/{action}/{title}/{version?}", make(<page>));
add-resource($wiki-app, "user/{action}/{name}", make(<user>));
add-resource($wiki-app, "group/{action}/{name}", make(<group>))
The URL path elements surrounded by curly braces are “path variables”. Let’s
decompose the first URL above: page/{action}/{title}/{version?}
. The first
element, “page” must be matched literally. The {action} and {title} elements
are required path variables; if either is missing 404 is returned. The last
element, {version?} is optional, as indicated by the ‘?’ character. (Two more
path variable types that aren’t shown here are available: {v*}
matches zero
or more path elements and {v+}
matches one or more.)
In order to define the behavior of our various resources we define methods on
the respond
generic function. Note that each path variable in the URL
passed to add-resource
corresponds to a keyword in the respond
method for the resource being added. (For our purposes the behavior will be to
simply display the values of all the path variables.)
define method respond
(resource :: <page>, #key action, title, version)
set-header(current-response(), "Content-Type", "text/html");
output("<html><body>action = %s, title = %s, version = %s</body></html>",
action, title, version);
end;
The respond
methods for <user>
and <group>
are similar. Notice
that version
may be #f
but action
and title
will always be
strings.
Lastly, we’ll connect $wiki-app
to the root URL (/) and start the server:
define constant $server = make(<http-server>, listeners: #("0.0.0.0:8888"));
add-resource($server, "/", $wiki-app);
start-server($server);
That’s it. Run the server and click on some of these URLs to see the corresponding behavior:
Here’s the full code listing:
-----------library.dylan------------
Module: dylan-user
define library web60-static-routing
use common-dylan;
use http-common;
use http-server;
end;
define module web60-static-routing
use common-dylan;
use http-common;
use http-server;
end;
-----------static-routing.dylan------------
Module: web60-static-routing
define constant $wiki-app = make(<resource>);
define class <page> (<resource>) end;
define class <user> (<resource>) end;
define class <group> (<resource>) end;
add-resource($wiki-app, "page/{action}/{title}/{version?}", make(<page>));
add-resource($wiki-app, "user/{action}/{name}", make(<user>));
add-resource($wiki-app, "group/{action}/{name}", make(<group>));
define method respond
(resource :: <page>, #key action, title, version)
set-header(current-response(), "Content-Type", "text/html");
output("<html><body>action = %s, title = %s, version = %s</body></html>",
action, title, version);
end;
define method respond
(resource :: type-union(<user>, <group>), #key action, name)
set-header(current-response(), "Content-Type", "text/html");
output("<html><body>action = %s, name = %s</body></html>",
action, name);
end;
define constant $server = make(<http-server>, listeners: #("0.0.0.0:8888"));
add-resource($server, "/", $wiki-app);
start-server($server);