HTTP-Response
The section describes how to create and send an HTTP response in Rapidy.
Description
HTTP Response is a message sent by the server to the client in response to their request.
Example of a text HTTP response (HTTP/1.1 protocol)
HTTP/1.1 200 OK
Server: Nginx
Content-Type: text/html; charset=utf-8
Date: Wed, 10 Aug 2024 11:00:00 GMT
Keep-Alive: timeout=5, max=1000
Connection: Keep-Alive
Age: 3464
Date: Wed, 10 Aug 2024 11:10:00 GMT
X-Cache-Info: caching
Content-Length: 220
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN>">
(... more body data ...)
Structure of an HTTP response
An HTTP response consists of a status line, headers, and a body.
Status Line
HTTP/1.1 200 OK
The status line (or status string) includes:
- Protocol version (HTTP protocol) — HTTP/1.1
- Status code (numerical code indicating the status of the request) — 200
- Explanation (brief textual description of the status code) — OK
HTTP Protocol Versions
HTTP standards are developed by the Internet Engineering Task Force (IETF) and the World Wide Web Consortium (W3C), resulting in a series of documents called Requests for Comments (RFC).
| Protocol Version | HTTP Protocol Type | Transport Layer | Description |
|---|---|---|---|
| HTTP/1.1 | Textual | TCP | Requires waiting for a response before sending the next request on the same connection. |
| HTTP/2 | Binary | TCP | Allows sending multiple requests simultaneously without waiting for the previous ones to finish. |
| HTTP/3/QUIC | Binary | UDP | Operates over UDP (uses QUIC technology). |
HTTP Status Codes
HTTP status codes inform the client of the result of processing their request. They are divided into five categories:
| Code | Description |
|---|---|
| 1xx | Informational codes, not affecting the request processing. |
| 2xx | Successful request processing. |
| 3xx | Redirection to another resource. |
| 4xx | Client-side errors (e.g., invalid request or lack of permissions). |
| 5xx | Server-side errors. |
Response Headers
Response headers (Response Headers) specify details about the response but do not affect the content of the body.
Examples of headers
| Category | Example | Description |
|---|---|---|
| Server | Server: nginx | Information about the server that handled the request. |
| Set-Cookie | Set-Cookie:UserData=SomeData123 | A cookie with user information stored by the browser. |
Response Body
An optional part of the response containing data.
The server specifies the type of transmitted data using the Content-Type header.
The response body can represent JSON, a media file, a document, text, or even an arbitrary set of bytes.
Generating an HTTP Response
A simple HTTP handler response might look like this:
from rapidy.http import get
@get('/')
async def handler() -> dict[str, str]:
return {'hello': 'rapidy'}
Validation and Serialization of the Response
Rapidy uses pydantic for validation and serialization of responses.
When the server starts, Rapidy creates a pydantic model for each handler based on the return annotation and uses it to validate data in the response.
You can override the type for validation or cancel the creation of the pydantic model using the response_validate and response_type attributes.
from rapidy.http import get
@get(
'/',
response_validate=False,
)
async def handler() -> str: # <-- `str` will be ignored
return {'hello': 'rapidy'}
More about response attributes for HTTP handlers can be read here.
Examples of successful responses
@post('/')
async def handler() -> int: # <-- `int` will be used to validate
return '123' # success response --> `123`
Examples of failed responses
from rapidy.http import get
@get('/')
async def handler() -> int: # <-- `int` will be used to validate
return 'some_data' # <-- will raise err
------------------------------
Validation errors:
[{'loc': ('body',),
'msg': 'Input should be a valid integer, unable to parse string as an '
'integer',
'type': 'int_parsing'}]
Handler path: `main.py`
Handler name: `handler`
------------------------------
Advanced HTTP Response Management
Rapidy uses the Response object for managing HTTP responses.
The Response object can be created either by Rapidy internally to form a response or by the developer for explicit control.
More about the Response object can be read here.
Automatic Creation of Response Object
Rapidy automatically creates a Response in the following cases:
If a handler defines an attribute with any name and type Response
This gives the developer more flexibility in managing HTTP responses, allowing, for example, setting status codes, cookies, and other parameters.
Learn more about the Response object attributes here.
from rapidy.http import get, Response
@get('/')
async def handler(
response: Response, # <-- current response
) -> str:
some_answer: bool = ...
if some_answer:
response.set_status(200)
return 'ok'
response.set_status(500)
return 'not ok'
You can also return the same Response object.
from rapidy.http import get, Response
@get('/')
async def handler(response: Response) -> Response:
return response
The handler returns a python object
from rapidy.http import get
@get('/')
async def handler() -> dict[str, str]:
return {'hello': 'rapidy'}
If a handler already has an attribute with type Response, and the handler returns a python object, a new instance of Response will not be created.
The handler returns a Response object
Rapidy allows the developer to manage and create the Response object manually.
from rapidy.http import get, Response
@get('/')
async def handler() -> Response:
return Response(status=201)
When directly managing the response, handler attributes are ignored.
If the Response object was injected as an attribute, and the developer returns a new Response, the injected Response is ignored.
When directly managing the response, pydantic validation will not work.
The handler returns None
If the Rapidy handler returns nothing, Rapidy will return the current Response object by default.
If you modified the request and returned nothing from the handler, this modified request will be returned!
from rapidy.http import get, Response
@get('/')
async def handler(response: Response) -> None:
response.text = 'hello rapidy!'
# success response --> `hello rapidy!`
HTTP Handler Attributes
The response attributes of a web handler are used to manage the formation of the response when returning any python object from the handler.
Default Status Code
To manage the default status code, you can define the status_code attribute.
from http import HTTPStatus
from rapidy.http import get
@get(
'/',
status_code=201,
)
async def handler() -> ...:
...
@get(
'/',
status_code=HTTPStatus.CREATED,
)
async def handler() -> ...:
...
You can read about other attributes here.
Rapidy allows you to manage attributes across all handler types, including those styled like aiohttp.