Response
All handlers usually return a response object, and middleware may optionally return a response object.
To clarify that statement:
- unless the handler is a streaming endpoint handling its own pattern for sending bytes to the client, the return value must be an instance of
sanic.response.HTTPResponse
(to learn more about this exception see streaming responses). In most use cases, you will need to return a response. - if a middleware does return a response object, that will be used instead of whatever the handler would do (see middleware to learn more).
A most basic handler would look like the following. The sanic.response.HTTPResponse
object will allow you to set the status, body, and headers to be returned to the client.
from sanic import HTTPResponse, Sanic
app = Sanic("TestApp")
@app.route("")
def handler(_):
return HTTPResponse()
However, usually it is easier to use one of the convenience methods discussed below.
Methods#
The easiest way to generate a response object is to use one of the convenience functions.
Text#
Default Content-Type: text/plain; charset=utf-8
Description: Returns plain text
from sanic import text
@app.route("/")
async def handler(request):
return text("Hi 😎")
HTML#
Default Content-Type: text/html; charset=utf-8
Description: Returns an HTML document
from sanic import html
@app.route("/")
async def handler(request):
return html('<!DOCTYPE html><html lang="en"><meta charset="UTF-8"><div>Hi 😎</div>')
JSON#
Default Content-Type: application/json
Description: Returns a JSON document
from sanic import json
@app.route("/")
async def handler(request):
return json({"foo": "bar"})
By default, Sanic ships with ujson
as its JSON encoder of choice. If ujson
is not installed, it will fall back to the standard library json
module.
It is super simple to change this if you want.
from sanic import json
from orjson import dumps
json({"foo": "bar"}, dumps=dumps)
You may additionally declare which implementation to use globally across your application at initialization:
from orjson import dumps
app = Sanic(..., dumps=dumps)
File#
Default Content-Type: N/A
Description: Returns a file
from sanic import file
@app.route("/")
async def handler(request):
return await file("/path/to/whatever.png")
Sanic will examine the file, and try and guess its mime type and use an appropriate value for the content type. You could be explicit, if you would like:
file("/path/to/whatever.png", mime_type="image/png")
You can also choose to override the file name:
file("/path/to/whatever.png", filename="super-awesome-incredible.png")
File Streaming#
Default Content-Type: N/A
Description: Streams a file to a client, useful when streaming large files, like a video
from sanic.response import file_stream
@app.route("/")
async def handler(request):
return await file_stream("/path/to/whatever.mp4")
Like the file()
method, file_stream()
will attempt to determine the mime type of the file.
Raw#
Default Content-Type: application/octet-stream
Description: Send raw bytes without encoding the body
from sanic import raw
@app.route("/")
async def handler(request):
return raw(b"raw bytes")
Redirect#
Default Content-Type: text/html; charset=utf-8
Description: Send a 302
response to redirect the client to a different path
from sanic import redirect
@app.route("/")
async def handler(request):
return redirect("/login")
Empty#
Default Content-Type: N/A
Description: For responding with an empty message as defined by RFC 2616
from sanic import empty
@app.route("/")
async def handler(request):
return empty()
Defaults to a 204
status.
Default status#
The default HTTP status code for the response is 200
. If you need to change it, it can be done by the response method.
@app.post("/")
async def create_new(request):
new_thing = await do_create(request)
return json({"created": True, "id": new_thing.thing_id}, status=201)
Returning JSON data#
Starting in v22.12, When you use the sanic.json
convenience method, it will return a subclass of HTTPResponse
called sanic.response.types.JSONResponse
. This object will
have several convenient methods available to modify common JSON body.
from sanic import json
resp = json(...)
resp.set_body(<raw_body>)
- Set the body of the JSON object to the value passedresp.append(<value>)
- Append a value to the body likelist.append
(only works if the root JSON is an array)resp.extend(<value>)
- Extend a value to the body likelist.extend
(only works if the root JSON is an array)resp.update(<value>)
- Update the body with a value likedict.update
(only works if the root JSON is an object)resp.pop()
- Pop a value likelist.pop
ordict.pop
(only works if the root JSON is an array or an object)
Warning
The raw Python object is stored on the JSONResponse
object as raw_body
. While it is safe to overwrite this value with a new one, you should not attempt to mutate it. You should instead use the methods listed above.
resp = json({"foo": "bar"})
# This is OKAY
resp.raw_body = {"foo": "bar", "something": "else"}
# This is better
resp.set_body({"foo": "bar", "something": "else"})
# This is also works well
resp.update({"something": "else"})
# This is NOT OKAY
resp.raw_body.update({"something": "else"})
# Or, even treat it like a list
resp = json(["foo", "bar"])
# This is OKAY
resp.raw_body = ["foo", "bar", "something", "else"]
# This is better
resp.extend(["something", "else"])
# This is also works well
resp.append("something")
resp.append("else")
# This is NOT OKAY
resp.raw_body.append("something")
Added in v22.9