So far we have seen a lot of this decorator in different forms. But what is it? And how do we use it?
@app.route("/stairway") . @app.get("/to") . @app.post("/heaven") .
The most basic way to wire up a handler to an endpoint is with app.add_route() . See API docs for more details.
async def handler(request): return text("OK") app.add_route(handler, "/test")
By default, routes are available as an HTTP GET call. You can change a handler to respond to one or more HTTP methods.
app.add_route( handler, '/test', methods=["POST", "PUT"], )
Using the decorator syntax, the previous example is identical to this.
@app.route('/test', methods=["POST", "PUT"]) async def handler(request): return text('OK')
@app.get('/test') async def handler(request): return text('OK')
@app.post('/test') async def handler(request): return text('OK')
@app.put('/test') async def handler(request): return text('OK')
@app.patch('/test') async def handler(request): return text('OK')
@app.delete('/test') async def handler(request): return text('OK')
@app.head('/test') async def handler(request): return empty()
@app.options('/test') async def handler(request): return empty()
Warning By default, Sanic will only consume the incoming request body on non-safe HTTP methods: POST , PUT , PATCH , DELETE . If you want to receive data in the HTTP request on any other method, you will need to do one of the following two options: Option #1 - Tell Sanic to consume the body using ignore_body
@app.request("/path", ignore_body=False) async def handler(_): .
Option #2 - Manually consume the body in the handler using receive_body
@app.get("/path") async def handler(request: Request): await request.receive_body()
Sanic allows for pattern matching, and for extracting values from URL paths. These parameters are then injected as keyword arguments in the route handler.
@app.get("/tag/") async def tag_handler(request, tag): return text("Tag - <>".format(tag))
You can declare a type for the parameter. This will be enforced when matching, and also will type cast the variable.
@app.get("/foo/") async def uuid_handler(request, foo_id: UUID): return text("UUID - <>".format(foo_id))
For some standard types like str , int , and UUID , Sanic can infer the path parameter type from the function signature. This means that it may not always be necessary to include the type in the path parameter definition.
@app.get("/foo/") # Notice there is no :uuid in the path parameter async def uuid_handler(request, foo_id: UUID): return text("UUID - <>".format(foo_id))
Beginning in v22.3 str will not match on empty strings. See strorempty for this behavior.
@app.route("/path/to/") async def handler(request, foo: str): .
Regular expression applied: r"[^/]*"
Cast type: str
Example matches:
Unlike the str path parameter type, strorempty can also match on an empty string path segment.
@app.route("/path/to/") async def handler(request, foo: str): .
Regular expression applied: r"-?\d+"
Cast type: int
Example matches:
Does not match float, hex, octal, etc
@app.route("/path/to/") async def handler(request, foo: int): .
Regular expression applied: r"-?(?:\d+(?:\.\d*)?|\.\d+)"
Cast type: float
Example matches:
@app.route("/path/to/") async def handler(request, foo: float): .
Regular expression applied: r"[A-Za-z]+"
Cast type: str
Example matches:
Does not match a digit, or a space or other special character
@app.route("/path/to/") async def handler(request, foo: str): .
Regular expression applied: r"[a-z0-9]+(?:-[a-z0-9]+)*"
Cast type: str
Example matches:
@app.route("/path/to/") async def handler(request, article: str): .
Regular expression applied: r"[^/].*?"
Cast type: str
Example matches:
@app.route("/path/to/") async def handler(request, foo: str): .
Because this will match on / , you should be careful and thoroughly test your patterns that use path so they do not capture traffic intended for another endpoint. Additionally, depending on how you use this type, you may be creating a path traversal vulnerability in your application. It is your job to protect your endpoint against this, but feel free to ask in our community channels for help if you need it :)
Regular expression applied: r"^([12]\d-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))"
Cast type: datetime.date
Example matches:
@app.route("/path/to/") async def handler(request, foo: datetime.date): .