guide/content/en/guide/basics/response.md
All handlers usually return a response object, and middleware may optionally return a response object.
To clarify that statement:
sanic.response.HTTPResponse (to learn more about this exception see streaming responses). In most use cases, you will need to return a response.A most basic handler would look like the following. The :class: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.
The easiest way to generate a response object is to use one of the convenience functions.
.. column::
**Default Content-Type**: `text/plain; charset=utf-8`
**Description**: Returns plain text
.. column::
```python
from sanic import text
@app.route("/")
async def handler(request):
return text("Hi 😎")
```
.. column::
**Default Content-Type**: `text/html; charset=utf-8`
**Description**: Returns an HTML document
.. column::
```python
from sanic import html
@app.route("/")
async def handler(request):
return html('<!DOCTYPE html><html lang="en"><meta charset="UTF-8"><div>Hi 😎</div>')
```
.. column::
**Default Content-Type**: `application/json`
**Description**: Returns a JSON document
.. column::
```python
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)
.. column::
**Default Content-Type**: N/A
**Description**: Returns a file
.. column::
```python
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")
.. column::
**Default Content-Type**: N/A
**Description**: Streams a file to a client, useful when streaming large files, like a video
.. column::
```python
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.
.. column::
**Default Content-Type**: `application/octet-stream`
**Description**: Send raw bytes without encoding the body
.. column::
```python
from sanic import raw
@app.route("/")
async def handler(request):
return raw(b"raw bytes")
```
.. column::
**Default Content-Type**: `text/html; charset=utf-8`
**Description**: Send a `302` response to redirect the client to a different path
.. column::
```python
from sanic import redirect
@app.route("/")
async def handler(request):
return redirect("/login")
```
.. column::
**Default Content-Type**: N/A
**Description**: For responding with an empty message as defined by [RFC 2616](https://tools.ietf.org/search/rfc2616#section-7.2.1)
.. column::
```python
from sanic import empty
@app.route("/")
async def handler(request):
return empty()
```
Defaults to a `204` 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)
Starting in v22.12, When you use the sanic.json convenience method, it will return a subclass of HTTPResponse called :class: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 like list.append (only works if the root JSON is an array)resp.extend(<value>) - Extend a value to the body like list.extend (only works if the root JSON is an array)resp.update(<value>) - Update the body with a value like dict.update (only works if the root JSON is an object)resp.pop() - Pop a value like list.pop or dict.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