2018-08-28 13:58:03 +00:00
Starlette includes a `Request` class that gives you a nicer interface onto
the incoming request, rather than accessing the ASGI scope and receive channel directly.
### Request
Signature: `Request(scope, receive=None)`
```python
2018-09-05 09:29:04 +00:00
from starlette.requests import Request
2019-02-24 18:40:09 +00:00
from starlette.responses import Response
2018-08-29 10:17:09 +00:00
2019-06-14 10:53:17 +00:00
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)
2018-08-28 13:58:03 +00:00
```
Requests present a mapping interface, so you can use them in the same
way as a `scope` .
For instance: `request['path']` will return the ASGI path.
If you don't need to access the request body you can instantiate a request
without providing an argument to `receive` .
#### Method
The request method is accessed as `request.method` .
#### URL
The request URL is accessed as `request.url` .
2018-10-05 10:29:06 +00:00
The property is a string-like object that exposes all the
2018-08-28 13:58:03 +00:00
components that can be parsed out of the URL.
For example: `request.url.path` , `request.url.port` , `request.url.scheme` .
#### Headers
Headers are exposed as an immutable, case-insensitive, multi-dict.
For example: `request.headers['content-type']`
#### Query Parameters
2019-01-23 09:04:33 +00:00
Query parameters are exposed as an immutable multi-dict.
2018-08-28 13:58:03 +00:00
2018-10-29 09:22:45 +00:00
For example: `request.query_params['search']`
#### Path Parameters
Router path parameters are exposed as a dictionary interface.
For example: `request.path_params['username']`
2018-08-28 13:58:03 +00:00
2018-12-14 09:58:27 +00:00
#### Client Address
2024-04-25 06:49:38 +00:00
The client's remote address is exposed as a named two-tuple `request.client` (or `None` ).
2018-12-14 09:58:27 +00:00
The hostname or IP address: `request.client.host`
The port number from which the client is connecting: `request.client.port`
2018-10-17 10:15:32 +00:00
#### Cookies
2018-10-17 10:17:07 +00:00
Cookies are exposed as a regular dictionary interface.
2018-10-17 10:15:32 +00:00
For example: `request.cookies.get('mycookie')`
2020-03-18 07:41:08 +00:00
Cookies are ignored in case of an invalid cookie. (RFC2109)
2018-08-28 13:58:03 +00:00
#### Body
There are a few different interfaces for returning the body of the request:
The request body as bytes: `await request.body()`
2023-02-06 05:58:21 +00:00
The request body, parsed as form data or multipart: `async with request.form() as form:`
2018-10-12 17:15:04 +00:00
2018-08-28 13:58:03 +00:00
The request body, parsed as JSON: `await request.json()`
You can also access the request body as a stream, using the `async for` syntax:
```python
2018-09-05 09:29:04 +00:00
from starlette.requests import Request
from starlette.responses import Response
2018-08-29 10:17:09 +00:00
2019-06-14 10:53:17 +00:00
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)
2018-08-28 13:58:03 +00:00
```
If you access `.stream()` then the byte chunks are provided without storing
2018-11-14 10:58:05 +00:00
the entire body to memory. Any subsequent calls to `.body()` , `.form()` , or `.json()`
2018-10-12 17:15:04 +00:00
will raise an error.
2019-01-15 09:59:59 +00:00
In some cases such as long-polling, or streaming responses you might need to
determine if the client has dropped the connection. You can determine this
state with `disconnected = await request.is_disconnected()` .
2019-02-19 13:14:53 +00:00
2019-03-04 19:25:03 +00:00
#### Request Files
Request files are normally sent as multipart form data (`multipart/form-data`).
2023-02-14 08:01:32 +00:00
Signature: `request.form(max_files=1000, max_fields=1000)`
You can configure the number of maximum fields or files with the parameters `max_files` and `max_fields` :
```python
async with request.form(max_files=1000, max_fields=1000):
...
```
!!! info
These limits are for security reasons, allowing an unlimited number of fields or files could lead to a denial of service attack by consuming a lot of CPU and memory parsing too many empty fields.
2023-02-06 05:58:21 +00:00
When you call `async with request.form() as form` you receive a `starlette.datastructures.FormData` which is an immutable
2019-03-04 19:25:03 +00:00
multidict, containing both file uploads and text input. File upload items are represented as instances of `starlette.datastructures.UploadFile` .
`UploadFile` has the following attributes:
2023-02-08 05:20:19 +00:00
* `filename` : An `str` with the original file name that was uploaded or `None` if its not available (e.g. `myimage.jpg` ).
* `content_type` : An `str` with the content type (MIME type / media type) or `None` if it's not available (e.g. `image/jpeg` ).
2019-03-04 19:25:03 +00:00
* `file` : A < a href = "https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" target = "_blank" > `SpooledTemporaryFile`</ a > (a < a href = "https://docs.python.org/3/glossary.html#term-file-like-object" target = "_blank" > file-like</ a > object). This is the actual Python file that you can pass directly to other functions or libraries that expect a "file-like" object.
2022-01-07 19:06:37 +00:00
* `headers` : A `Headers` object. Often this will only be the `Content-Type` header, but if additional headers were included in the multipart field they will be included here. Note that these headers have no relationship with the headers in `Request.headers` .
2023-02-06 12:02:29 +00:00
* `size` : An `int` with uploaded file's size in bytes. This value is calculated from request's contents, making it better choice to find uploaded file's size than `Content-Length` header. `None` if not set.
2019-03-04 19:25:03 +00:00
`UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile` ).
2022-01-10 17:41:43 +00:00
* `async write(data)` : Writes `data` (`bytes`) to the file.
* `async read(size)` : Reads `size` (`int`) bytes of the file.
2019-03-04 19:25:03 +00:00
* `async seek(offset)` : Goes to the byte position `offset` (`int`) in the file.
* E.g., `await myfile.seek(0)` would go to the start of the file.
* `async close()` : Closes the file.
As all these methods are `async` methods, you need to "await" them.
For example, you can get the file name and the contents with:
```python
2023-02-06 05:58:21 +00:00
async with request.form() as form:
filename = form["upload_file"].filename
contents = await form["upload_file"].read()
2019-03-04 19:25:03 +00:00
```
2022-06-27 04:56:00 +00:00
!!! info
As settled in [RFC-7578: 4.2 ](https://www.ietf.org/rfc/rfc7578.txt ), form-data content part that contains file
2022-08-06 21:46:06 +00:00
assumed to have `name` and `filename` fields in `Content-Disposition` header: `Content-Disposition: form-data;
name="user"; filename="somefile"`. Though `filename` field is optional according to RFC-7578, it helps
2022-06-27 04:56:00 +00:00
Starlette to differentiate which data should be treated as file. If `filename` field was supplied, `UploadFile`
object will be created to access underlying file, otherwise form-data part will be parsed and available as a raw
string.
2022-01-07 19:06:37 +00:00
2019-08-27 22:11:03 +00:00
#### Application
The originating Starlette application can be accessed via `request.app` .
2019-02-19 13:14:53 +00:00
#### Other 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()`