Serving Dynamic Content#

Previous: Serving Static Content

Back to top

This example will show how to dynamically generate the contents of a web page.

First, the ever-exciting library and module definitions. In addition to common-dylan and http-server we need streams for writing data to the response and date so we can show something dynamic happening:

define library web60-dynamic-content
  use common-dylan;
  use io, import: { streams };
  use http-common;
  use http-server;
  use system, import: { date };
end;

define module web60-dynamic-content
  use common-dylan;
  use date, import: { as-iso8601-string, current-date };
  use http-common;
  use http-server;
  use streams, import: { write };
end;

A web page is a resource mapped to a URL inside the web server. To create a resource we subclass <resource>:

define class <clock-page> (<resource>) end;

To make our resource do something we define a method on respond. (If we only wanted to implement the GET request method we could define a method on respond-to-get instead.)

define method respond (page :: <clock-page>, #key)
  let stream = current-response();
  set-header(stream, "Content-Type", "text/html");
  let date = as-iso8601-string(current-date());
  write(stream, concatenate("<html><body>", date, "</body></html>"));
end;

current-response returns the active <response> object. To send data back to the client we write to the current response.

let server = make(<http-server>,
                  listeners: list("0.0.0.0:8888"));
add-resource(server, "/", make(<clock-page>));
start-server(server);

In the previous example we already saw how to create and start a server, so the new bit here is using add-resource to map a URL to a <resource>. The first argument to add-resource is the URL router. (In Routes terminology it would be a “mapper”.) For convenience, an <http-server> is a kind of router so we can add resources directly to the server. In a future example, I will show how to do more complex URL routing, which will explain the reason for the mysterious #key in the respond definition above.

Here’s the complete code:

---- File: library.dylan ----
Module: dylan-user

define library web60-dynamic-content
  use common-dylan;
  use io, import: { streams };
  use http-common;
  use http-server;
  use system, import: { date };
end;

define module web60-dynamic-content
  use common-dylan;
  use date, import: { as-iso8601-string, current-date };
  use http-common;
  use http-server;
  use streams, import: { write };
end;

---- File: main.dylan ----
Module: web60-dynamic-content

define class <clock-page> (<resource>)
end;

define method respond (page :: <clock-page>, #key)
  let stream = current-response();
  set-header(stream, "Content-Type", "text/html");
  let date = as-iso8601-string(current-date());
  write(stream, concatenate("<html><body>", date, "</body></html>"));
end;

let server = make(<http-server>,
                  listeners: list("0.0.0.0:8888"));
add-resource(server, "/", make(<clock-page>));
start-server(server);

Back to top