Routing

To include shallot builtin routing use the routing-middleware: wrap_routes:

build_server(apply_middleware(wrap_routes(routes))(default_handler))

The routing-middleware is somewhat special, to other middlewares. It does not enhance the request/response, but chooses a new handler for the specific request. If the router can’t find a matching handler for the route, then the default_handler will be passed into the next middleware(s).

Examples

Routing is completely defined via a data-structure:

async def hello_world(request):
    return text("hi user!")

# handle_index is attached to a "dynamic"-route with one parseable url-part -> thus it needs to accept request and one additional parameter
async def handle_index(request, idx):
    return text(f"hi user number: {idx}")


routes = [
    ("/", ["GET"], hello_world),
    ("/hello", ["GET"], hello_world),
    ("/hello/{index}", ["GET"], handle_index),
    ("/echo", ["GET", "PUT", "POST"], post_echo),
    ("/json", ["GET", "PUT"], show_and_accept_json),
]

as shown above, routes is a list of tuples with:

1. the (potentially dynamic) route
2. the allowed methods
3. the handler

routes with an {tag} in it, are considered dynamic-routes. The router will parse the value from the url and passed it (as string) to the handler-function as parameter. Therefor the handler function must accept the request and as many arguments as there are {tag}s.

Discussion

maybe one controversial one upfront: trailing slashes are ignored. In the defined routes and in the matching of requests too.

routing is one essential and by far, the most opinionated part of any webframeworks-api. shallot is there no exception.