We begin the book in this first chapter by showing how basic web applications can be written using just a few lines of code. In the second chapter we will treat the construction of web applications more in depth, also touching on the fundamentals of web application building. But we start by keeping it simple, which is possible thanks to Teapot.
Teapot is a micro web framework on top of the Zinc HTTP web server described in Chapter Zinc Server. It focuses on simplicity and ease of use and is itself small: around 600 lines of code, not counting unit tests. Teapot is developed by Attila Magyar and this chapter is heavily inspired from the original documentation.
To get started, execute the following code snippet, it will load the latest stable version of Teapot.
It is straightforward to launch Teapot and add a page:
Opening a browser on http://localhost:1701/welcome results in the following:
Teapot is not a singleton and doesn't hold any global state. You can run multiple Teapot servers inside the same image with their state being isolated from each other.
Before getting into the details of Teapot. Here is a simple example for managing books. With the following code, we can list books, add a book and delete a book.
Now you can create a book with ZnClient or your web client as follows:
You can also list the contents using http://localhost:8080/books
For a more complete example, study the
Now that you get the general feel of Teapot, let us see the key concepts.
The most important concept of Teapot is the Route. The template for route definitions is as follows:
A route has three parts:
/foo/*/bar/*, or a regular expression),
In the expression below, the three rules are equivalent:
The first one returns directly the value of an instance value; the second the value returned by the message; the third will send the message
books: with as parameter the request as show below; the fourth will take a request as argument and execute the block.
Here is another example:
A wildcard character (
*), as in the last route, matches to one URL path segment. A wildcard terminated pattern is a greedy match;
'/foo/*' for example matches to
The second route shows that the action block optionally takes the HTTP request. The third route is an example of a message send, by using the
Send class. The selector of the message can take maximum 2 arguments, which will be instances of
It is also possible to use the Zinc client (see Chapter Zinc Client Side) to query the server. The example below illustrates the use of parameters, which we discuss next.
The URL pattern may contain named parameters (e.g.,
<user> above), whose values are accessible via the request object. The request is an extension of
ZnRequest with some extra methods.
Query parameters and Form parameters can be accessed the same way as path parameters
(req at: #paramName). Teapot can perform conversions of parameters to a number, for example as follows:
IsIntegermatches digits (negative or positive) only and converts the value to an Integer.
IsNumbermatches any integer or floating point number and converts the value to a Number.
See also the,
IsNumber classes for information about introducing user defined conversions.
> surrounded named parameters, the regexp pattern may contain subexpressions between parentheses whose values are accessible via the
The following example matches any
/hi/user followed by two digits.
The routes are matched in the order in which they are defined.
The first route that matches the request method and the URL is invoked.
ZnResponse, no transformation will be performed.
abort: message sent to the request object immediately stops a request (by signaling an exception) within a route. For example:
The default output for Teapot is HTML: the output of an action is interpreted as a string and the content-type of the HTML response is set to
text/html. The output of an action may actually undergo any kind of transformations by a response transformer. Response Transformers have the ultimate responsibility for constructing the outgoing HTTP response (an instance of the class
ZnResponse). To clarify, HTTP requests take the following path through Teapot:
The response returned by the action can be:
TeaResponsethat allows additional parameters to be added (response code, headers).
ZnResponsethat will be handled directly by the
ZnServerwithout further transformation.
For example, the following three routes produce the same output.
The responsibility of a response transformer is to convert the output of the action block to HTML and to set the content-type of the response.
Some response transformers require external packages (e.g., NeoJSON, STON, Mustache). See the
TeaOutput class for more information, for example the HTML transformer is
For example, with the following configuration:
Figure 0.2 shows the result for the
If the NeoJSON package is loaded (See
chapter NeoJSON.) the
jsonlist transformer will return a JSON array:
If you have a file located
/tmp/afile you can access it
If Mustache is installed (See chapter Mustache.) you can output templated information.
Teapot also offers before and after filters.
Before filters are evaluated before each request that matches the given URL pattern. Requests can also be aborted (by sending the
abort: message) in before and after filters.
In the following example a before filter is used to enable authentication: if the session has no
#user attribute, the browser is redirected to a login page.
After filters are evaluated after each request and can read the request and modify the response.
Teapot also handles exceptions of a configured type(s) for all routes and before filters. The following example illustrates how the errors raised in actions can be captured by exception handlers.
/div/6/3 succeeds and returns 2. The request
/div/6/0 raises an error and it is caught and returns
a bad request.
You can use a comma-separated exception set to handle multiple exceptions.
The same rules apply for the return values of the exception handler as were used for the Routes.
The POST method is commonly used for HTML form submission. When a POST request comes in the form data will be accessible via the request parameter. The request object has a generic
at: method that can be used to access the path, query or form parameters in a uniform way.
The following example shows how to create a simple login form.
The /login URL is linked to two actions, one for GET requests and another for POST requests. The first one displays a HTML login form to the user. The second action is invoked on a form submission and checks the given login credentials.
The request body can be accessed directly using
req entity contents. This is useful when interacting with JSON or XML request body contents instead of HTML forms.
Teapot can straightforwardly serve static files. The following example serves the files located on the file system at
/var/www/htdocs at the
Teapot is a powerful and simple web framework. It is based on the notion of routes and request transformations. It supports the definition of REST application.
Now an important point: Where does the name come from? 418 I'm a teapot (RFC 2324) is an HTTP status code. It was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, and is not expected to be implemented by actual HTTP servers.