The Request Object¶
The Request object encapsulates all the information
passed by the client. It is passed as an argument to route handlers, as well as
to before-request, after-request and error handlers.
Request Attributes¶
The request object provides access to the request attributes, including:
method: The HTTP method of the request.path: The path of the request.args: The query string parameters of the request, as aMultiDictobject.headers: The headers of the request, as a dictionary.cookies: The cookies that the client sent with the request, as a dictionary.content_type: The content type specified by the client, orNoneif no content type was specified.content_length: The content length of the request, or 0 if no content length was specified.json: The parsed JSON data in the request body. See below for additional details.form: The parsed form data in the request body, as a dictionary. See below for additional details.files: A dictionary with the file uploads included in the request body. Note that file uploads are only supported when the Multipart Forms extension is used.client_addr: The network address of the client, as a tuple (host, port).app: The application instance that created the request.g: Thegobject, where handlers can store request-specific data to be shared among handlers. See The “g” Object for details.
JSON Payloads¶
When the client sends a request that contains JSON data in the body, the
application can access the parsed JSON data using the
json attribute. The following example shows how
to use this attribute:
@app.post('/customers')
async def create_customer(request):
customer = request.json
# do something with customer
return {'success': True}
Note
The client must set the Content-Type header to application/json for
the json attribute of the request object to be populated.
Form Data¶
The request object also supports standard HTML form submissions through the
form attribute, which presents the form data
as a MultiDict object. Example:
@app.route('/', methods=['GET', 'POST'])
async def index(req):
name = 'Unknown'
if req.method == 'POST':
name = req.form.get('name')
return f'Hello {name}'
Note
Form submissions automatically parsed when the Content-Type header is
set by the client to application/x-www-form-urlencoded. For form
submissions that use the multipart/form-data content type the
Multipart Forms extension must be used.
Accessing the Raw Request Body¶
For cases in which neither JSON nor form data is expected, the
body request attribute returns the entire body
of the request as a byte sequence.
If the expected body is too large to fit safely in memory, the application can
use the stream request attribute to read the
body contents as a file-like object. The
max_body_length attribute of the
request object defines the size at which bodies are streamed instead of loaded
into memory.
The “g” Object¶
Sometimes applications need to store data during the lifetime of a request, so
that it can be shared between the before- and after-request handlers, the
route function and any error handlers. The request object provides the
g attribute for that purpose.
In the following example, a before request handler authorizes the client and stores the username so that the route function can use it:
@app.before_request
async def authorize(request):
username = authenticate_user(request)
if not username:
return 'Unauthorized', 401
request.g.username = username
@app.get('/')
async def index(request):
return f'Hello, {request.g.username}!'
Request-Specific After-Request Handlers¶
Sometimes applications need to perform operations on the response object
before it is sent to the client, for example to set or remove a cookie. A good
option to use for this is to define a request-specific after-request handler
using the after_request decorator.
Request-specific after-request handlers are called by Microdot after the route
function returns and all the application-wide after-request handlers have been
called.
The next example shows how a cookie can be updated using a request-specific after-request handler defined inside a route function:
@app.post('/logout')
async def logout(request):
@request.after_request
def reset_session(request, response):
response.set_cookie('session', '', http_only=True)
return response
return 'Logged out'
Request Limits¶
To help prevent malicious attacks, Microdot provides some configuration options to limit the amount of information that is accepted:
max_content_length: The maximum size accepted for the request body, in bytes. When a client sends a request that is larger than this, the server will respond with a 413 error. The default is 16KB.max_body_length: The maximum size that is loaded in thebodyattribute, in bytes. Requests that have a body that is larger than this size but smaller than the size set formax_content_lengthcan only be accessed through thestreamattribute. The default is also 16KB.max_readline: The maximum allowed size for a request line, in bytes. The default is 2KB.
The following example configures the application to accept requests with payloads up to 1MB in size, but prevents requests that are larger than 8KB from being loaded into memory:
from microdot import Request
Request.max_content_length = 1024 * 1024
Request.max_body_length = 8 * 1024