Skip to content

Requests

Starlette contains an Request class that gives you a friendlier interface to handle incoming requests rather than direct access to ASGI scopes and receive channels.

request

Signed by: Request(scope, receive=None)

from starlette.requests import Request
from starlette.responses import Response


async def app(scope, receive, send):
    assert scope['type'] == 'http'
    request = Request(scope, receive)
    content = '%s %s' % (request.method, request.url.path)
    response = Response(content, media_type='text/plain')
    await response(scope, receive, send)

Requests provide a mapping interface, so you can use them just as you would scope.

For example:request['path'] will return the ASGI path.

If you do not need access to the request body, you can instantiate the request without supplying parameters to receive.

method

The request method is accessed as request.method.

Uniform Resource Locator (also commonly referred to simply as URL)

The requested URL/request.url.html was not found on this server.

This property is a string-like object that exposes all components that can be parsed from the URL.

For example:request.url.path,request.url.port,request.url.scheme.

headline

The header is exposed as an immutable, case-insensitive multidictionary.

For example: request.headers['content-type']

query parameter

Query parameters are exposed as immutable multiple dictionaries.

For example: request.query_params['search']

path parameters

Router path parameters are exposed as dictionary interfaces.

For example: request.path_params['username']

customer address

The client's remote address is exposed as a binary called request.client (or None )。

The hostname or IP address: request.client.host

Port number the client is connecting to: request.client.port

Cookies

Cookies are presented in the form of regular dictionary interfaces.

For example: request.cookies.get('mycookie')

Cookies are ignored in case of invalid cookies.(RFC2109)

body

There are several different interfaces for returning the body of the request:

Request body in bytes: await request.body()

Request body, parsed into form data or multipart: async with request.form() as form:

Request body, parsed to JSON: await request.json()

You can also access the request body as a stream using async for syntax:

from starlette.requests import Request
from starlette.responses import Response


async def app(scope, receive, send):
    assert scope['type'] == 'http'
    request = Request(scope, receive)
    body = b''
    async for chunk in request.stream():
        body += chunk
    response = Response(body, media_type='text/plain')
    await response(scope, receive, send)

If you access .stream(), a byte chunk is provided instead of storing the entire body in memory. Any subsequent calls to .body(),.form(), or .json() will raise an error.

In some cases, such as long polling or streaming responses, you may need to determine if the client has disconnected. You can determine this status using disconnected = await request.is_disconnected().

request file

Request files are usually sent as multipart form data (multipart/form-data).

Signed by: request.form(max_files=1000, max_fields=1000)

You can configure the maximum number of fields or files using the parameters max_files and max_fields:

async with request.form(max_files=1000, max_fields=1000):
    ...

The!!! message sets these limits for security reasons, and allowing an unlimited number of fields or files can lead to denial of service attacks because parsing too many empty fields consumes a lot of CPU and memory.

When you call async with request.form() as form, you receive an starlette.datastructures.FormData, which is an immutable multidictionary containing file uploads and text input. File uploads are represented as instances of starlette.datastructures.UploadFile.

UploadFile Has the following attributes:

  • filename:str with the original filename uploaded, or None if unavailable (e.g.myimage.jpg).
  • content_type:str with content type (MIME type/media type) or None if unavailable (e.g.image/jpeg).
  • file: an SpooledTemporaryFile(a file-like object). This is the actual Python file, which you can pass directly to other functions or libraries expecting a "file-like" object.
  • headers: an Headers object. Usually this will just be the Content-Type header, but if other headers are included in the multipart field, they will be included here as well. Note that these headers have nothing to do with the headers in Request.headers.
  • size: an int of the upload file size in bytes. This value is calculated based on the content of the request and is therefore a better choice for determining the upload file size than the Content-Length header. If not set,None.

UploadFile has the following async methods. They all call the corresponding file methods at the bottom (using the internal SpooledTemporaryFile).

  • async write(data): writes data(bytes) to a file.
  • async read(size) : Read the file's size ( int ) byte.
  • async seek(offset): Go to byte position offset(int) in the file.
    • For example,await myfile.seek(0) goes to the beginning of the file.
  • async close() : Close the file.

Since all of these methods are async methods, you need to "wait" for them.

For example, you can get the file name and content by:

async with request.form() as form:
    filename = form["upload_file"].filename
    contents = await form["upload_file"].read()

!!! information As specified in RFC - 7578: 4.2, the form data content section containing the file assumes name and filename fields in the Content-Disposition header:Content-Disposition: form-data; name="user"; filename="somefile". Although the filename field is optional according to RFC - 7578, it helps Starlette distinguish what data should be considered a file. If the filename field is provided, an UploadFile object is created to access the underlying file, otherwise the form data portion is parsed and available as the original string.

application program

The Starlette application is accessible via request.app.

state

If you want to store additional information on the request, you can do so using request.state.

For example:

request.state.time_started = time.time()