# Request

The Request instance contains a lot of helpful information available on its parameters. Refer to the API documentation (opens new window) for full details.

# Body

    # Context

    # Request context

    The request.ctx object is your playground to store whatever information you need to about the request.

    This is often used to store items like authenticated user details. We will get more into middleware later, but here is a simple example.

    @app.on_request
    async def run_before_handler(request):
        request.ctx.user = await fetch_user_by_token(request.token)
    @app.route('/hi')
    async def hi_my_name_is(request):
        return text("Hi, my name is {}".format(request.ctx.user.name))
    

    A typical use case would be to store the user object acquired from database in an authentication middleware. Keys added are accessible to all later middleware as well as the handler over the duration of the request.

    Custom context is reserved for applications and extensions. Sanic itself makes no use of it.

    # Connection context

    Often times your API will need to serve multiple concurrent (or consecutive) requests to the same client. This happens, for example, very often with progressive web apps that need to query multiple endpoints to get data.

    The HTTP protocol calls for an easing of overhead time caused by the connection with the use of keep alive headers.

    When multiple requests share a single connection, Sanic provides a context object to allow those requests to share state.

    @app.on_request
    async def increment_foo(request):
        if not hasattr(request.conn_info.ctx, "foo"):
            request.conn_info.ctx.foo = 0
        request.conn_info.ctx.foo += 1
    @app.get("/")
    async def count_foo(request):
        return text(f"request.conn_info.ctx.foo={request.conn_info.ctx.foo}")
    
    $ curl localhost:8000 localhost:8000 localhost:8000
    request.conn_info.ctx.foo=1
    request.conn_info.ctx.foo=2
    request.conn_info.ctx.foo=3
    

    # Parameters

    Values that are extracted from the path are injected into the handler as parameters, or more specifically as keyword arguments. There is much more detail about this in the Routing section.

    @app.route('/tag/<tag>')
    async def tag_handler(request, tag):
        return text("Tag - {}".format(tag))
    

    # Arguments

    There are two attributes on the request instance to get query parameters:

    • request.args
    • request.query_args
    $ curl http://localhost:8000\?key1\=val1\&key2\=val2\&key1\=val3
    
    >>> print(request.args)
    {'key1': ['val1', 'val3'], 'key2': ['val2']}
    >>> print(request.args.get("key1"))
    val1
    >>> print(request.args.getlist("key1"))
    ['val1', 'val3']
    >>> print(request.query_args)
    [('key1', 'val1'), ('key2', 'val2'), ('key1', 'val3')]
    >>> print(request.query_string)
    key1=val1&key2=val2&key1=val3
    

    FYI

    💡 The request.args object is one of a few types that is a dictionary with each value being a list. This is because HTTP allows a single key to be reused to send multiple values.

    Most of the time you will want to use the .get() method to access the first element and not a list. If you do want a list of all items, you can use .getlist().

    MIT Licensed
    Copyright © 2018-present Sanic Community Organization

    ~ Made with ❤️ and ☕️ ~