Response

Sending responses

Route handlers should return a response that will be sent back to the client. Expanse supports sending various types of responses: HTML fragments, JSON objects, files, and more.

Using native Python types

In simple cases, you can return native objects that will be automatically converted to a response:

def hello_world() -> str:
    return "Hello world!"


def json_object() -> dict[str, Any]:
    return {"foo": "bar"}


router.get("/hello", hello_world)
router.get("/json", json_object)

In these cases Expanse will automatically convert the returned value to a JSON (application/json) response.

Using response objects

Most of the time you will want to return more complex responses than simple strings or dictionaries. Instead, you will return Response instances or views, which will give you more control over the status code, headers or cookies of the response.

from expanse.http.response import Response


def hello_world() -> Response:
    response = Response("Hello world!", 200)
    response.headers["Content-Type"] = "application/json"

    return response

Using a responder

Response objects are bare-bone and provide only the minimum functionality needed to return standard responses. If you prefer a more expressive way to return responses, you can use a Responder instance instead. The responder provides a fluent interface to generate responses and additional intuitive features.

from expanse.http.responder import Responder
from expanse.http.response import Response


def hello_world(responder: Responder) -> Response:
    return responder.json("Hello world!", 200)

A Responder instance is a flexible way to generate different types of responses, like redirects, views or JSON responses.

Headers

You can set headers on the response object to control the response behavior by using the with_header() method:

from expanse.http.responder import Responder
from expanse.http.response import Response


def hello_world(responder: Responder) -> Response:
    return (
        responder.json("Hello world!", 200)
        .with_header("X-Header-One", "Value")
        .with_header("X-Header-Two", "Value")
    )

You can also use with_headers() to specify multiple headers to be added to the response:

from expanse.http.responder import Responder
from expanse.http.response import Response


def hello_world(responder: Responder) -> Response:
    return responder.json("Hello world!", 200).with_headers(
        {"X-Header-One": "Value", "X-Header-Two": "Value"}
    )

Redirection

If you need to redirect the user to a specific URL, you retrieve a Redirect instance from the Responder by using the redirect() method:

from expanse.http.responder import Responder
from expanse.http.response import Response


def profile(responder: Responder) -> Response:
    return responder.redirect().to("/me/profile")

Redirecting to named routes

If you want to redirect to a named route, you can use the to_route() method of the Redirect instance:

from expanse.http.responder import Responder
from expanse.http.response import Response


def profile(responder: Responder) -> Response:
    return responder.redirect().to_route("user.profile")

If the named route requires parameters, you can specify them as a dictionary:

responder.redirect().to_route("user.profile", {"id": 1})

Any additional parameters will be added to the query string of the generated URL:

responder.redirect().to_route("users.retrieve", {"id": 1, "extended": "true"})