Getting started

By default, grole will run a simple static file server in the current directory. To use this simply execute grole.py, or run python -m grole.

To serve your own functions, you first need a Grole object. The constructor accepts a env variable which is passed to your handler functions such that you can share state between them. Logging is done by the python logging module, if you want logging then run logging.basicConfig(level=logging.INFO).

Once you have setup handler functions for your web API, you can then launch the server with Grole.run(). This takes the host and port to serve on and does not return until interrupted.

Registering routes

Routes are registered to a Grole object by decorating a function with the Grole.route() decorator. The decorator function takes a regular expression as the path to match, an array of HTTP methods (GET, POST, etc), and whether you want this function in the API doc. Docstrings of functions in the API doc are available through env[‘doc’] within the handler function.

The order in which routes are registered is the order in which they will be tested when searching for a handler for a specific request.

Handling requests

Decorated functions registered to a Grole object with Grole.route() will be called if their associated regular expression matches that of a request (as well as the HTTP method).

A registered handler is given the following objects:

  • env: The env dictionary that the Grole object was constructed with
  • req: A Request object containing the full details of the request. The re.MatchObject from the path match is also added in as req.match.

We now know enough to make a simple web API. An example of how to return the hex value when visiting /<inteter> is shown below:

from grole import Grole

app = Grole()

def tohex(env, req):
    return hex(int(req.match.group(1)))


If you need to do something async within your handler, e.g. access a database using aioodbc then simply declare your handler as async and await as needed.


In-built python types returned by registered request handlers are automatically converted into 200 OK HTTP responses. The following mappings apply:

  • bytes: Sent directly with content type text/plain
  • string: Encoded as bytes and sent with content type text/html
  • others: Encoded as json and sent with content type application/json

Finer grained control of the response data can be achieved using ResponseBody or one of it’s children. These allow for overriding of the content type. The following are available:

Control of the headers in the response can be achieved by returning a Response object. This allows for sending responses other than 200 OK, for example.


Various helper functions are provided to simplify common operations:

  • serve_static(): Serve static files under a directory. Optionally provide simple directory indexes.
  • serve_doc(): Serve API documentation (docstrings) of registered request handlers using a simple plain text format.