Response Types

A list of the different HTTP response types available to your FastHTML route handlers.

FastHTML provides multiple HTTP response types that automatically set the appropriate HTTP content type and handle serialization. The main response types are:

What about websockets?

Websockets have their own protocol and don’t follow the HTTP request/response cycle. To learn more, check out our explanation about websockets here.

Configuration

from fasthtml.common import *
app,rt = fast_app()

app and rt are the common FastHTML route handler decorators. We instantiate them with the fast_app function.

cli = Client(app)

FastHTML comes with the test client named Client. It allows us to test handlers via a simple interface where .get() is a HTTP GET request, .post() is a HTTP POST request.

FT Component Response

@rt('/ft')
def get(): return Html(Div('FT Component Response'))

This is the response type you’re probably most familiar with. Here the route handler returns an FT component, which FastHTML wraps in an HTML document with a head and body.

print(cli.get('/ft').text)
 <!doctype html>
 <html>
   <div>FT Component Response</div>
 </html>

Redirect Response

@rt('/rr')
def get(): return Redirect('https://fastht.ml/')

Here in this route handler, Redirect redirects the user’s browser to the new URL ‘https://fastht.ml/’

resp = cli.get('/rr')
print(resp.url)
print(resp.status_code)
http://testserver/rr
303

You can see the URL in the response headers and url attribute, as well as a status code of 303.

JSON Response

@rt('/json')
def get(): return {'hello': 'world'}

This route handler returns a JSON response, where the content-type has been set to .

resp = cli.get('/json')
print(resp.headers)
print(resp.json())
Headers({'content-length': '17', 'content-type': 'application/json'})
{'hello': 'world'}

You can see that the Content-Type header has been set to application/json, and that the response is simply the JSON without any HTML wrapping it.

EventStream

from time import sleep

def counter():
    """Counter is an generator that
        publishes a number every second.
    """
    for i in range(3):
        yield sse_message(f"Event {i}")
        sleep(1)

@rt('/stream')
def get():
    return EventStream(counter())

With server-sent events, it’s possible for a server to send new data to a web page at any time, by pushing messages to the web page. Unlike WebSockets, SSE can only go in one direction: server to client. SSE is also part of the HTTP specification unlike WebSockets which uses its own specification.

resp = cli.get('/stream')
print(resp.text)
event: message
data: Event 0

event: message
data: Event 1

event: message
data: Event 2

Each one of the message events above arrived one second after the previous message event.

Plaintext Response

@rt('/text')
def get(): return 'Hello world'

When you return a string from a route handler, you get a plain-text response.

print(cli.get('/text').text)
Hello world

Here you can see that the response text is simply the string you returned, without any HTML wrapping it.