Name | areion JSON |
Version |
1.1.11
JSON |
| download |
home_page | None |
Summary | A lightweight, fast, and extensible asynchronous Python web server framework. |
upload_time | 2024-10-12 20:14:23 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | Copyright (c) 2024 Joshua Caponigro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
keywords |
python
api
framework
web
web-framework
http-server
|
VCS |
|
bugtrack_url |
|
requirements |
apscheduler
jinja2
orjson
uvloop
httptools
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Areion Server
[![License][license-shield]][license-url] [![Downloads](https://static.pepy.tech/badge/areion)](https://pepy.tech/project/areion)
[![Downloads](https://static.pepy.tech/badge/areion/month)](https://pepy.tech/project/areion)
[![PyPi][pypi-shield]][pypi-url] [![PyPi][pypiversion-shield]][pypi-url]
Welcome to the Areion HTTP Server documentation. Areion is a lightweight, asynchronous HTTP server written in Python, designed for simplicity and extensibility. This documentation provides a comprehensive guide to using Areion, covering everything from getting started to advanced usage and component details.
Areion supports asynchronous operations, multithreading, routing, orchestration, customizable loggers, and template engines. The framework provides an intuitive API for building web services, with components like the `Orchestrator`, `Router`, `Logger`, and `Engine` easily swappable or extendable.
We designed Areion to have as few dependencies as possible. We created our own HTTP server on top of asyncio's sockets. While we dream of being the fastest, most preferred Python web server, we know we have a long way to go. We are still in the early stages of development, and we welcome any feedback, contributions, or suggestions. The documentation below is likely to become outdated as we continue to migrate to v2.0.0 which will feature a whole documentation site with more examples, tutorials, and guides.
**Development Mode:** Add the flag `with_development_mode(True)` to the `AreionServerBuilder` to enable development mode. This mode will automatically add Swagger UI and OpenAPI routes to your server. They are accessible from the routes `/docs` and `/openapi` respectively.
## Table of Contents
- [Benchmark](#benchmark)
- [Benchmark Results](#benchmark-results)
- [Summary](#summary)
- [Visualization](#visualization)
- [Detailed Results](#detailed-results)
- [Analysis](#analysis)
- [Throughput (Requests per Second)](#throughput-requests-per-second)
- [Average Latency](#average-latency)
- [Total Requests Handled](#total-requests-handled)
- [Socket Errors](#socket-errors)
- [Getting Started](#getting-started)
- [Installation](#installation)
- [Developing](#developing)
- [Quick Start Guide](#quick-start-guide)
- [Development Tools](#development-tools)
- [Core Components](#core-components)
- [AreionServer](#areionserver)
- [Router](#router)
- [FastAPI-like Route Definition Example](#fastapi-like-route-definition-example)
- [Subrouter (Grouping Routes) Example](#subrouter-grouping-routes-example)
- [Django-like Route Definition Example](#django-like-route-definition-example)
- [HttpServer](#httpserver)
- [Default Component Implementation](#default-component-implementation)
- [Orchestrator](#orchestrator)
- [Logger](#logger)
- [Engine](#engine)
- [Advanced Usage](#advanced-usage)
- [Middleware](#middleware)
- [Grouping Routes](#grouping-routes)
- [Template Rendering](#template-rendering)
- [Task Scheduling](#task-scheduling)
- [API Reference](#api-reference)
- [AreionServer API](#areionserver-api)
- [Router API](#router-api)
- [HttpRequest and HttpResponse](#httprequest-and-httpresponse)
- [HttpRequest](#httprequest)
- [HttpResponse](#httpresponse)
- [Response Utility Functions](#response-utility-functions)
- [Exception Handling](#exception-handling)
- [Best Practices](#best-practices)
- [Responses](#responses)
- [Missing HTTP/1.1 Features](#missing-http11-features)
- [Contributing](#contributing)
- [License](#license)
---
## Benchmark
We conducted performance benchmarks to compare **Areion**, **FastAPI**, and **Flask**, focusing on throughput and latency under high-load conditions. The goal was to evaluate each framework's ability to handle concurrent connections efficiently and provide fast response times. We used the same JSON response in all frameworks to ensure a fair comparison.
### Benchmark Results
These show the results of running the benchmark test for 30 seconds with 12 threads and 400 connections on my local machine. The test was conducted using the `wrk` benchmarking tool. The results are summarized below, followed by detailed output for each framework.
#### Summary
| Framework | Requests/sec | Avg Latency (ms) | Transfer/sec | Total Requests | Socket Errors |
| --------- | ------------ | ---------------- | ------------ | -------------- | ------------------------- |
| Areion | 47,241.97 | 8.46 | 4.42 MB | 1,418,550 | Read: 545 |
| FastAPI | 3,579.10 | 111.53 | 531.27 KB | 107,613 | Read: 419 |
| Flask | 555.98 | 47.45 | 104.79 KB | 16,708 | Connect: 74, Read: 36,245 |
#### Visualization
![Requests per Second](assets/requests_per_second.png)
![Average Latency](assets/average_latency.png)
#### Detailed Results
**Results show the performance when keep-alive connections are used (HTTP/1.1 default). Areion still significantly outperforms when the header `Connection: close` is set.**
**Areion**
```bash
Running 30s test @ http://localhost:8000/json
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.46ms 2.06ms 47.38ms 95.91%
Req/Sec 3.96k 430.06 5.36k 87.17%
1,418,550 requests in 30.03s, 132.58MB read
Socket errors: connect 0, read 545, write 0, timeout 0
Requests/sec: 47,241.97
Transfer/sec: 4.42MB
```
**FastAPI**
```bash
Running 30s test @ http://localhost:8000/json
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 111.53ms 31.97ms 498.08ms 89.55%
Req/Sec 300.08 59.85 430.00 86.17%
107,613 requests in 30.07s, 15.60MB read
Socket errors: connect 0, read 419, write 0, timeout 0
Requests/sec: 3,579.10
Transfer/sec: 531.27KB
```
**Flask**
```bash
Running 30s test @ http://localhost:8000/json
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 47.45ms 53.33ms 556.78ms 96.24%
Req/Sec 183.12 104.16 590.00 70.64%
16,708 requests in 30.05s, 3.08MB read
Socket errors: connect 74, read 36,245, write 125, timeout 0
Requests/sec: 555.98
Transfer/sec: 104.79KB
```
### Analysis
#### Throughput (Requests per Second)
- **Areion:** 47,241.97 requests/sec
- **FastAPI:** 3,579.10 requests/sec
- **Flask:** 555.98 requests/sec
Areion handled approximately 13 times more requests per second than FastAPI and 85 times more than Flask.
#### Average Latency
- **Areion:** 8.46 ms
- **Flask:** 47.45 ms
- **FastAPI:** 111.53 ms
Areion's average latency is about 5.6 times lower than Flask and 13 times lower than FastAPI, indicating faster response times.
#### Total Requests Handled
- **Areion:** 1,418,550 requests
- **FastAPI:** 107,613 requests
- **Flask:** 16,708 requests
Areion processed significantly more total requests during the test duration.
#### Socket Errors
- **Areion:** Read errors: 545
- **FastAPI:** Read errors: 419
- **Flask:** Connect errors: 74, Read errors: 36,245, Write errors: 125
For handling 10x the requests of FastAPI and 85x the requests of Flask, Areion had a relatively low number of socket errors.
## Getting Started
### Installation
Areion can be installed via pip:
```bash
pip install areion
```
### Developing
To get started developing this project, follow these steps:
1. Clone the repository:
```bash
git clone https://github.com/JoshCap20/areion.git
```
2. Install the dependencies (preferably in a virtual environment):
```bash
pip install -r requirements.txt
```
3. Run the tests:
```bash
pytest
```
### Quick Start Guide
Below is a simple example to get you started with Areion.
```python
from areion import AreionServerBuilder, DefaultRouter, HttpRequest
# Initialize the router
router = DefaultRouter()
# Define a simple route
@router.route("/hello")
def hello_world(request: HttpRequest):
return "Hello, World!"
# Build and run the server
server = AreionServerBuilder().with_router(router).build()
server.run()
```
**Explanation:**
- **Router Initialization:** We create a Router instance to manage our routes.
- **Defining Routes:** Using the @router.route decorator, we define a route that responds to /hello.
- **Server Building:** We use AreionServerBuilder to construct the server with the router.
- **Running the Server:** The server.run() method starts the server synchronously.
### Development Tools
Development tools are essential to increasing development ease and efficiency. With this in mind, we also don't want to slow down the server in production. To enable development tools, add the `with_development_mode(True)` flag to the `AreionServerBuilder`.
**Development Tools:**
- **Swagger UI:** Provides an interactive API documentation interface.
- **OpenAPI Routes:** Exposes auto-generated OpenAPI schema and routes for API exploration.
**Coming Soon:**
- **Automatic Reload:** Automatically reloads the server on code changes.
- **Debugging Tools:** Built-in debugging tools for inspecting requests and responses.
- **Testing Tools:** Integration with testing frameworks for automated testing.
- **Security Tools:** Security checks and recommendations for your server.
- **Performance Tools:** Performance monitoring and optimization tools.
## Core Components
### AreionServer
The `AreionServer` is the main class that represents the server. It manages components such as the router, orchestrator, logger, and HTTP server.
**Key Features:**
- **Asynchronous Operation:** Built on top of asyncio for non-blocking operations.
- **Component Integration:** Integrates with router, orchestrator, and other components.
- **Static File Serving:** Supports serving static files.
_Do not initialize AreionServer directly unless you know what you're doing. Use AreionServerBuilder to create an instance which includes safeguards and defaults required for other components._
#### AreionServerBuilder
The `AreionServerBuilder` provides a fluent interface for constructing an AreionServer instance with the desired components and configurations.
**Only a router is required for a minimal server setup.**
**Example:**
```python
from areion import AreionServerBuilder, DefaultRouter, DefaultLogger, DefaultOrchestrator, DefaultEngine
router = DefaultRouter()
logger = DefaultLogger()
orchestrator = DefaultOrchestrator()
engine = DefaultEngine()
server = AreionServerBuilder().with_router(router).with_logger(logger).with_orchestrator(orchestrator).with_port(8080).with_engine(engine).with_static_dir("static").build()
```
### Router
The `Router` class manages URL routes and their corresponding handlers. If no methods are defined, it defaults to only accepting GET requests. You can define middleware at the route, route group, or global level.
**Key Features:**
- **Dynamic Routing:** Supports dynamic path segments (e.g., /user/:id).
- **Method Specification:** Handlers can specify allowed HTTP methods.
- **Middleware Support:** Allows adding global and route-specific middleware.
#### FastAPI-like Route Definition Example
This default usage is similar to Flask and FastAPI, with decorators for defining routes and middleware.
**Usage:**
```python
from areion import DefaultRouter
router = DefaultRouter()
# Adding a route with a dynamic segment
@router.route("/user/:id", methods=["GET"])
def get_user(request, id):
return f"User ID: {id}"
# Adding global middleware
def log_request(handler):
def wrapper(request, *args, **kwargs):
print(f"Received request: {request.path}")
return handler(request, *args, **kwargs)
return wrapper
router.add_global_middleware(log_request)
```
#### Subrouter (Grouping Routes) Example
`main.py`:
```python
from areion import DefaultRouter
from areion import (
AreionServer,
AreionServerBuilder,
DefaultLogger,
DefaultEngine,
DefaultRouter,
HttpResponse
)
from users import users_router
main_router = DefaultRouter()
main_router.include_router(users_router)
logger = DefaultLogger(log_file="server.log")
engine = DefaultEngine()
server: AreionServer = (
AreionServerBuilder()
.with_router(main_router)
.with_engine(engine)
.with_logger(logger)
.build()
)
if __name__ == "__main__":
server.run()
```
`users.py`:
```python
from areion import DefaultRouter, HttpResponse
users_router = DefaultRouter(prefix="/users")
@users_router.route("/", methods=["GET"])
def get_all_users(request):
return HttpResponse(status_code=200, body={"users": []}, content_type="application/json")
@users_router.route("/:user_id", methods=["GET"])
def get_user(request, user_id):
body = request.get_parsed_body()
if not body.get("token"):
return HttpResponse(status_code=401, body="Unauthorized", content_type="text/plain")
return HttpResponse(status_code=200, body={"user_id": user_id}, content_type="application/json")
```
#### Django-like Route Definition Example
You can also use a Django-like syntax for defining routes:
```python
router = DefaultRouter()
def get_user(request, id):
return f"User ID: {id}"
router.add_route("/user/:id", get_user, methods=["GET"])
```
Route with middleware:
```python
router = DefaultRouter()
def get_user(request, id):
return f"User ID: {id}"
def log_request(handler):
def wrapper(request, *args, **kwargs):
print(f"Received request: {request.path}")
return handler(request, *args, **kwargs)
return wrapper
router.add_route("/user/:id", get_user, methods=["GET"], middlewares=[log_request])
```
### HttpServer
The `HttpServer` class handles the low-level HTTP protocol details.
**Key Features:**
- **Request Handling:** Processes incoming HTTP requests.
- **Response Sending:** Formats and sends HTTP responses.
- **Connection Management:** Manages client connections asynchronously.
**Usage:**
This class is usually managed internally by `AreionServer` and doesn't require direct interaction.
## Default Component Implementation
Areion provides default implementations for several core components that can be used out of the box. These components are designed to work together seamlessly and provide a solid foundation for building web applications. Feel free to use these default components or create your own custom implementations according to the interfaces in `areion/base`.
### Orchestrator
The `Orchestrator` class manages background tasks and scheduling. The startup and shutdown are managed by the `AerionServer`.
**Key Features:**
- **Task Submission:** Allows submitting tasks to be executed asynchronously.
- **Scheduling:** Supports scheduling tasks using cron expressions.
- **Thread Management:** Uses a thread pool for concurrent execution.
**Usage:**
```python
from areion import DefaultOrchestrator
orchestrator = DefaultOrchestrator(max_workers=4)
def background_task():
print("Running background task")
# Submit a task
orchestrator.submit_task(background_task)
# Schedule a cron task
orchestrator.schedule_cron_task(background_task, {'hour': '*/1'})
```
### Logger
The `Logger` class provides logging capabilities. This logger is passed to multiple other components and also injected into each HttpRequest that is accesible in every route handler.
**Key Features:**
- **Configurable Levels:** Supports standard logging levels (INFO, DEBUG, ERROR, etc.).
- **File and Console Logging:** Can log to both files and the console.
- **Formatter Support:** Customizable log formatting.
**Usage:**
```python
from areion import DefaultLogger, AreionServerBuilder, DefaultRouter
router = DefaultRouter()
logger = DefaultLogger(log_file="server.log", log_level="INFO")
@router.route("/log", methods=["GET"])
def some_handler(request):
logger.info("Processing request")
return "Response"
server = AreionServerBuilder().with_router(router).with_logger(logger).build()
```
### Engine
The `Engine` class handles template rendering.
**Key Features:**
**Jinja2 Integration:** Uses Jinja2 for template rendering.
**Template Directory:** Configurable template directory.
**Usage:**
```python
from areion import DefaultEngine
engine = Engine(templates_dir="templates")
# Rendering a template
def home(request):
context = {"title": "Home"}
return request.render_template("home.html", context)
```
## Advanced Usage
### Middleware
Middleware functions allow you to process requests and responses globally or for specific routes.
**Creating Middleware:**
```python
def auth_middleware(handler):
def wrapper(request, *args, **kwargs):
if not request.get_header("Authorization"):
return HttpResponse(status_code=401, body="Unauthorized")
return handler(request, *args, **kwargs)
return wrapper
```
**Applying Middleware:**
**Global Middleware:**
```python
router.add_global_middleware(auth_middleware)
```
**Route-specific Middleware:**
```python
@router.route("/dashboard", middlewares=[auth_middleware])
def dashboard(request):
return "Welcome to the dashboard"
```
### Grouping Routes
You can group routes under a common path and apply middlewares to the group.
**Usage:**
```python
# Define group-specific middleware
def group_middleware(handler):
def wrapper(request, *args, **kwargs):
print("Group middleware executed")
return handler(request, *args, **kwargs)
return wrapper
# Create a route group
api_group = router.group("/api", middlewares=[group_middleware])
@api_group.route("/users")
def api_users(request):
return "API Users"
@api_group.route("/posts")
def api_posts(request):
return "API Posts"
```
### Template Rendering
Use the Engine component to render templates with dynamic content.
**Usage:**
```python
def profile(request):
user_data = {"name": "John Doe", "age": 30}
return request.render_template("profile.html", user_data)
```
### Task Scheduling
Schedule tasks to run at specified intervals using the Orchestrator.
**Usage:**
```python
def cleanup_task():
print("Performing cleanup")
# Schedule to run every day at midnight
orchestrator.schedule_cron_task(cleanup_task, {'hour': '0', 'minute': '0'})
```
## API Reference
### AreionServer API
#### AreionServer
Represents the main server class.
**Constructor Parameters:**
- `host (str)`: Server host address.
- `port (int)`: Server port number.
- `router (Router)`: Router instance.
- `orchestrator (Orchestrator, optional)`: Orchestrator instance.
- `logger (Logger, optional)`: Logger instance.
- `engine (Engine, optional)`: Template engine instance.
- `static_dir (str, optional)`: Directory for static files.
**Methods:**
- `run()`: Starts the server synchronously.
- `start()`: Starts the server asynchronously.
- `stop()`: Initiates server shutdown.
#### AreionServerBuilder
Builder class for constructing AreionServer instances.
**Methods:**
- `with_host(host)`: Sets the server host.
- `with_port(port)`: Sets the server port.
- `with_router(router)`: Sets the router.
- `with_orchestrator(orchestrator)`: Sets the orchestrator.
- `with_logger(logger)`: Sets the logger.
- `with_engine(engine)`: Sets the template engine.
- `with_static_dir(static_dir)`: Sets the static directory.
- `with_development_mode(bool)`: Enables development mode and Swagger UI/OpenAPI routes.
- `build()`: Builds and returns an AreionServer instance.
### Router API
#### Router
Manages URL routes and their handlers.
**Methods:**
- `add_route(path, handler, methods, middlewares)`: Adds a route.
- `route(path, methods, middlewares)`: A decorator to define a route with optional middlewares.
- `include_router(router)`: Includes all routes from the given sub-router into the current router.
- `group(base_path, middlewares)`: Creates a sub-router with a base path and optional group-specific middlewares.
- `add_global_middleware(middleware)`: Adds a middleware that will be applied globally to all routes.
- `get_handler(method, path)`: Retrieves the handler for a given path and method.
- `get_allowed_methods(path)`: Retrieves the allowed methods for a given path.
### HttpRequest and HttpResponse
#### HttpRequest
Represents an HTTP request. These are injected into each route handler as the first argument via the HttpServer.
**Attributes:**
- `method (str)`: HTTP method.
- `path (str)`: Request path.
- `headers (dict)`: Request headers.
- `metadata (dict)`: Additional metadata.
- `body (str)`: Request body.
- `path (str)`: Request path.
- `query_params (dict)`: Query parameters.
**Methods:**
- `add_header(key, value)`: Adds a header.
- `get_header(key)`: Retrieves a header value.
- `get_parsed_body()`: Retrieves the request body as a dictionary.
- `get_raw_body()`: Retrieves the raw request body.
- `get_query_param(key)`: Retrieves a query parameter.
- `get_raw_query_params()`: Retrieves the raw query parameters.
- `get_parsed_query_params()`: Retrieves the query parameters as a dictionary.
- `add_metadata(key, value)`: Adds metadata.
- `get_metadata(key)`: Retrieves metadata.
- `render_template(template_name, context)`: Renders a template.
- `submit_task(task, *args)`: Submits a task to the orchestrator.
- `log(message, level)`: Logs a message.
- `as_dict()`: Converts the request to a dictionary.
#### HttpResponse
Represents an HTTP response.
**Constructor Parameters:**
- `body (any)`: Response body.
- `status_code (int)`: HTTP status code.
- `content_type (str, optional)`: Content type.
- `headers (dict, optional)`: Additional headers.
**Methods:**
- `format_response()`: Formats the response for sending.
- `set_header(key, value)`: Sets a header.
- `set_headers(headers)`: Sets multiple headers.
- `set_status_code(status_code)`: Sets the status code.
#### Response Utility Functions
- `create_file_response(file_path: str, status_code: int = 200)`: Creates a response for a file given a filepath.
- `create_json_response(data: dict, status_code: int = 200)`: Creates a JSON response.
- `create_text_response(text: str, status_code: int = 200)`: Creates a text response.
- `create_html_response(html: str, status_code: int = 200)`: Creates an HTML response.
- `create_redirect_response(location: str, status_code: int = 302)`: Creates a redirect response.
- `create_error_response(status_code: int, message: str = None, headers: dict = None)`: Creates an error response.
- `create_empty_response(status_code: int = 204, headers: dict = None)`: Creates an empty response.
## Exception Handling
Areion provides custom exceptions for common HTTP errors. These exceptions can be raised in route handlers to return the corresponding error response and status code.
- `HttpError`: Base class for HTTP errors.
- `BadRequestError`: Corresponds to 400 Bad Request.
- `UnauthorizedError`: Corresponds to 401 Unauthorized.
- `ForbiddenError`: Corresponds to 403 Forbidden.
- `NotFoundError`: Corresponds to 404 Not Found.
- `MethodNotAllowedError`: Corresponds to 405 Method Not Allowed.
- `InternalServerError`: Corresponds to 500 Internal Server Error.
**Easily create custom exceptions by subclassing the HttpError class.**
**Usage:**
```python
from areion import NotFoundError
def get_item(request, item_id):
item = database.get(item_id)
if not item:
raise NotFoundError("Item not found")
return item
```
_Exceptions in routes and middleware are handled globally and converted to a proper HTTP response._
## Best Practices
### Responses
We recommend returning a `HttpResponse` object directly from route handlers. This allows for more control over the response status code, headers, and body. Additionally, it is recommended, but not required, to pass an explicit `content_type` during construction for performance reasons.
_Helpful wrappers now exist in the `areion/utils/response_utils.py` to make this easier for common use cases._
_Make sure that objects are JSON serializable before returning them in the response body._
**Example:**
```python
from areion import HttpResponse
@router.route("/user", methods=GET)
def get_user(request):
user = {
"name": "John Doe",
"age": 30
}
return HttpResponse(body=user, content_type="application/json")
```
## Missing HTTP/1.1 Features
- **Chunked Transfer Encoding:** Areion does not support chunked transfer encoding yet.
- **Compression:** Areion does not support compression yet.
- **Caching:** Areion does not support caching yet.
- **Cookies:** Areion does not support cookies yet.
- **Range Requests:** Areion does not support range requests yet.
## Contributing
Contributions are welcome! For feature requests, bug reports, or questions, please open an issue. If you would like to contribute code, please open a pull request with your changes.
## License
MIT License
Copyright (c) 2024 Joshua Caponigro
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software.
[pypi-shield]: https://img.shields.io/pypi/pyversions/areion?color=281158
[pypi-url]: https://pypi.org/project/areion/
[pypiversion-shield]: https://img.shields.io/pypi/v/areion?color=361776
[license-url]: https://github.com/JoshCap20/areion/blob/main/LICENSE
[license-shield]: https://img.shields.io/github/license/joshcap20/areion
Raw data
{
"_id": null,
"home_page": null,
"name": "areion",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "python, api, framework, web, web-framework, http-server",
"author": null,
"author_email": "Josh Caponigro <joshcaponigro@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/0e/66/627562dd62b6b1ab49122510e825c54d04e98894a4ada3fe07710c0ac5bf/areion-1.1.11.tar.gz",
"platform": null,
"description": "# Areion Server\n\n[![License][license-shield]][license-url] [![Downloads](https://static.pepy.tech/badge/areion)](https://pepy.tech/project/areion)\n[![Downloads](https://static.pepy.tech/badge/areion/month)](https://pepy.tech/project/areion)\n\n[![PyPi][pypi-shield]][pypi-url] [![PyPi][pypiversion-shield]][pypi-url]\n\nWelcome to the Areion HTTP Server documentation. Areion is a lightweight, asynchronous HTTP server written in Python, designed for simplicity and extensibility. This documentation provides a comprehensive guide to using Areion, covering everything from getting started to advanced usage and component details.\n\nAreion supports asynchronous operations, multithreading, routing, orchestration, customizable loggers, and template engines. The framework provides an intuitive API for building web services, with components like the `Orchestrator`, `Router`, `Logger`, and `Engine` easily swappable or extendable.\n\nWe designed Areion to have as few dependencies as possible. We created our own HTTP server on top of asyncio's sockets. While we dream of being the fastest, most preferred Python web server, we know we have a long way to go. We are still in the early stages of development, and we welcome any feedback, contributions, or suggestions. The documentation below is likely to become outdated as we continue to migrate to v2.0.0 which will feature a whole documentation site with more examples, tutorials, and guides.\n\n**Development Mode:** Add the flag `with_development_mode(True)` to the `AreionServerBuilder` to enable development mode. This mode will automatically add Swagger UI and OpenAPI routes to your server. They are accessible from the routes `/docs` and `/openapi` respectively.\n\n## Table of Contents\n\n- [Benchmark](#benchmark)\n - [Benchmark Results](#benchmark-results)\n - [Summary](#summary)\n - [Visualization](#visualization)\n - [Detailed Results](#detailed-results)\n - [Analysis](#analysis)\n - [Throughput (Requests per Second)](#throughput-requests-per-second)\n - [Average Latency](#average-latency)\n - [Total Requests Handled](#total-requests-handled)\n - [Socket Errors](#socket-errors)\n- [Getting Started](#getting-started)\n - [Installation](#installation)\n - [Developing](#developing)\n - [Quick Start Guide](#quick-start-guide)\n - [Development Tools](#development-tools)\n- [Core Components](#core-components)\n - [AreionServer](#areionserver)\n - [Router](#router)\n - [FastAPI-like Route Definition Example](#fastapi-like-route-definition-example)\n - [Subrouter (Grouping Routes) Example](#subrouter-grouping-routes-example)\n - [Django-like Route Definition Example](#django-like-route-definition-example)\n - [HttpServer](#httpserver)\n- [Default Component Implementation](#default-component-implementation)\n - [Orchestrator](#orchestrator)\n - [Logger](#logger)\n - [Engine](#engine)\n- [Advanced Usage](#advanced-usage)\n - [Middleware](#middleware)\n - [Grouping Routes](#grouping-routes)\n - [Template Rendering](#template-rendering)\n - [Task Scheduling](#task-scheduling)\n- [API Reference](#api-reference)\n - [AreionServer API](#areionserver-api)\n - [Router API](#router-api)\n - [HttpRequest and HttpResponse](#httprequest-and-httpresponse)\n - [HttpRequest](#httprequest)\n - [HttpResponse](#httpresponse)\n - [Response Utility Functions](#response-utility-functions)\n- [Exception Handling](#exception-handling)\n- [Best Practices](#best-practices)\n - [Responses](#responses)\n- [Missing HTTP/1.1 Features](#missing-http11-features)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Benchmark\n\nWe conducted performance benchmarks to compare **Areion**, **FastAPI**, and **Flask**, focusing on throughput and latency under high-load conditions. The goal was to evaluate each framework's ability to handle concurrent connections efficiently and provide fast response times. We used the same JSON response in all frameworks to ensure a fair comparison.\n\n### Benchmark Results\n\nThese show the results of running the benchmark test for 30 seconds with 12 threads and 400 connections on my local machine. The test was conducted using the `wrk` benchmarking tool. The results are summarized below, followed by detailed output for each framework.\n\n#### Summary\n\n| Framework | Requests/sec | Avg Latency (ms) | Transfer/sec | Total Requests | Socket Errors |\n| --------- | ------------ | ---------------- | ------------ | -------------- | ------------------------- |\n| Areion | 47,241.97 | 8.46 | 4.42 MB | 1,418,550 | Read: 545 |\n| FastAPI | 3,579.10 | 111.53 | 531.27 KB | 107,613 | Read: 419 |\n| Flask | 555.98 | 47.45 | 104.79 KB | 16,708 | Connect: 74, Read: 36,245 |\n\n#### Visualization\n\n![Requests per Second](assets/requests_per_second.png)\n\n![Average Latency](assets/average_latency.png)\n\n#### Detailed Results\n\n**Results show the performance when keep-alive connections are used (HTTP/1.1 default). Areion still significantly outperforms when the header `Connection: close` is set.**\n\n**Areion**\n\n```bash\nRunning 30s test @ http://localhost:8000/json\n 12 threads and 400 connections\n Thread Stats Avg Stdev Max +/- Stdev\n Latency 8.46ms 2.06ms 47.38ms 95.91%\n Req/Sec 3.96k 430.06 5.36k 87.17%\n 1,418,550 requests in 30.03s, 132.58MB read\n Socket errors: connect 0, read 545, write 0, timeout 0\nRequests/sec: 47,241.97\nTransfer/sec: 4.42MB\n```\n\n**FastAPI**\n\n```bash\nRunning 30s test @ http://localhost:8000/json\n 12 threads and 400 connections\n Thread Stats Avg Stdev Max +/- Stdev\n Latency 111.53ms 31.97ms 498.08ms 89.55%\n Req/Sec 300.08 59.85 430.00 86.17%\n 107,613 requests in 30.07s, 15.60MB read\n Socket errors: connect 0, read 419, write 0, timeout 0\nRequests/sec: 3,579.10\nTransfer/sec: 531.27KB\n```\n\n**Flask**\n\n```bash\nRunning 30s test @ http://localhost:8000/json\n 12 threads and 400 connections\n Thread Stats Avg Stdev Max +/- Stdev\n Latency 47.45ms 53.33ms 556.78ms 96.24%\n Req/Sec 183.12 104.16 590.00 70.64%\n 16,708 requests in 30.05s, 3.08MB read\n Socket errors: connect 74, read 36,245, write 125, timeout 0\nRequests/sec: 555.98\nTransfer/sec: 104.79KB\n```\n\n### Analysis\n\n#### Throughput (Requests per Second)\n\n- **Areion:** 47,241.97 requests/sec\n- **FastAPI:** 3,579.10 requests/sec\n- **Flask:** 555.98 requests/sec\n\nAreion handled approximately 13 times more requests per second than FastAPI and 85 times more than Flask.\n\n#### Average Latency\n\n- **Areion:** 8.46 ms\n- **Flask:** 47.45 ms\n- **FastAPI:** 111.53 ms\n\nAreion's average latency is about 5.6 times lower than Flask and 13 times lower than FastAPI, indicating faster response times.\n\n#### Total Requests Handled\n\n- **Areion:** 1,418,550 requests\n- **FastAPI:** 107,613 requests\n- **Flask:** 16,708 requests\n\nAreion processed significantly more total requests during the test duration.\n\n#### Socket Errors\n\n- **Areion:** Read errors: 545\n- **FastAPI:** Read errors: 419\n- **Flask:** Connect errors: 74, Read errors: 36,245, Write errors: 125\n\nFor handling 10x the requests of FastAPI and 85x the requests of Flask, Areion had a relatively low number of socket errors.\n\n## Getting Started\n\n### Installation\n\nAreion can be installed via pip:\n\n```bash\npip install areion\n```\n\n### Developing\n\nTo get started developing this project, follow these steps:\n\n1. Clone the repository:\n\n```bash\ngit clone https://github.com/JoshCap20/areion.git\n```\n\n2. Install the dependencies (preferably in a virtual environment):\n\n```bash\npip install -r requirements.txt\n```\n\n3. Run the tests:\n\n```bash\npytest\n```\n\n### Quick Start Guide\n\nBelow is a simple example to get you started with Areion.\n\n```python\n\nfrom areion import AreionServerBuilder, DefaultRouter, HttpRequest\n\n# Initialize the router\nrouter = DefaultRouter()\n\n# Define a simple route\n@router.route(\"/hello\")\ndef hello_world(request: HttpRequest):\n return \"Hello, World!\"\n\n# Build and run the server\nserver = AreionServerBuilder().with_router(router).build()\nserver.run()\n```\n\n**Explanation:**\n\n- **Router Initialization:** We create a Router instance to manage our routes.\n- **Defining Routes:** Using the @router.route decorator, we define a route that responds to /hello.\n- **Server Building:** We use AreionServerBuilder to construct the server with the router.\n- **Running the Server:** The server.run() method starts the server synchronously.\n\n### Development Tools\n\nDevelopment tools are essential to increasing development ease and efficiency. With this in mind, we also don't want to slow down the server in production. To enable development tools, add the `with_development_mode(True)` flag to the `AreionServerBuilder`.\n\n**Development Tools:**\n\n- **Swagger UI:** Provides an interactive API documentation interface.\n- **OpenAPI Routes:** Exposes auto-generated OpenAPI schema and routes for API exploration.\n\n**Coming Soon:**\n\n- **Automatic Reload:** Automatically reloads the server on code changes.\n- **Debugging Tools:** Built-in debugging tools for inspecting requests and responses.\n- **Testing Tools:** Integration with testing frameworks for automated testing.\n- **Security Tools:** Security checks and recommendations for your server.\n- **Performance Tools:** Performance monitoring and optimization tools.\n\n## Core Components\n\n### AreionServer\n\nThe `AreionServer` is the main class that represents the server. It manages components such as the router, orchestrator, logger, and HTTP server.\n\n**Key Features:**\n\n- **Asynchronous Operation:** Built on top of asyncio for non-blocking operations.\n- **Component Integration:** Integrates with router, orchestrator, and other components.\n- **Static File Serving:** Supports serving static files.\n\n_Do not initialize AreionServer directly unless you know what you're doing. Use AreionServerBuilder to create an instance which includes safeguards and defaults required for other components._\n\n#### AreionServerBuilder\n\nThe `AreionServerBuilder` provides a fluent interface for constructing an AreionServer instance with the desired components and configurations.\n\n**Only a router is required for a minimal server setup.**\n\n**Example:**\n\n```python\nfrom areion import AreionServerBuilder, DefaultRouter, DefaultLogger, DefaultOrchestrator, DefaultEngine\n\nrouter = DefaultRouter()\nlogger = DefaultLogger()\norchestrator = DefaultOrchestrator()\nengine = DefaultEngine()\n\nserver = AreionServerBuilder().with_router(router).with_logger(logger).with_orchestrator(orchestrator).with_port(8080).with_engine(engine).with_static_dir(\"static\").build()\n```\n\n### Router\n\nThe `Router` class manages URL routes and their corresponding handlers. If no methods are defined, it defaults to only accepting GET requests. You can define middleware at the route, route group, or global level.\n\n**Key Features:**\n\n- **Dynamic Routing:** Supports dynamic path segments (e.g., /user/:id).\n- **Method Specification:** Handlers can specify allowed HTTP methods.\n- **Middleware Support:** Allows adding global and route-specific middleware.\n\n#### FastAPI-like Route Definition Example\n\nThis default usage is similar to Flask and FastAPI, with decorators for defining routes and middleware.\n\n**Usage:**\n\n```python\nfrom areion import DefaultRouter\n\nrouter = DefaultRouter()\n\n# Adding a route with a dynamic segment\n@router.route(\"/user/:id\", methods=[\"GET\"])\ndef get_user(request, id):\n return f\"User ID: {id}\"\n\n# Adding global middleware\ndef log_request(handler):\n def wrapper(request, *args, **kwargs):\n print(f\"Received request: {request.path}\")\n return handler(request, *args, **kwargs)\n return wrapper\n\nrouter.add_global_middleware(log_request)\n```\n\n#### Subrouter (Grouping Routes) Example\n\n`main.py`:\n\n```python\nfrom areion import DefaultRouter\n\nfrom areion import (\n AreionServer,\n AreionServerBuilder,\n DefaultLogger,\n DefaultEngine,\n DefaultRouter,\n HttpResponse\n)\nfrom users import users_router\n\nmain_router = DefaultRouter()\nmain_router.include_router(users_router)\n\nlogger = DefaultLogger(log_file=\"server.log\")\nengine = DefaultEngine()\n\nserver: AreionServer = (\n AreionServerBuilder()\n .with_router(main_router)\n .with_engine(engine)\n .with_logger(logger)\n .build()\n)\n\nif __name__ == \"__main__\":\n server.run()\n```\n\n`users.py`:\n\n```python\nfrom areion import DefaultRouter, HttpResponse\n\nusers_router = DefaultRouter(prefix=\"/users\")\n\n@users_router.route(\"/\", methods=[\"GET\"])\ndef get_all_users(request):\n return HttpResponse(status_code=200, body={\"users\": []}, content_type=\"application/json\")\n\n@users_router.route(\"/:user_id\", methods=[\"GET\"])\ndef get_user(request, user_id):\n body = request.get_parsed_body()\n if not body.get(\"token\"):\n return HttpResponse(status_code=401, body=\"Unauthorized\", content_type=\"text/plain\")\n return HttpResponse(status_code=200, body={\"user_id\": user_id}, content_type=\"application/json\")\n```\n\n#### Django-like Route Definition Example\n\nYou can also use a Django-like syntax for defining routes:\n\n```python\nrouter = DefaultRouter()\n\ndef get_user(request, id):\n return f\"User ID: {id}\"\n\nrouter.add_route(\"/user/:id\", get_user, methods=[\"GET\"])\n```\n\nRoute with middleware:\n\n```python\nrouter = DefaultRouter()\n\ndef get_user(request, id):\n return f\"User ID: {id}\"\n\ndef log_request(handler):\n def wrapper(request, *args, **kwargs):\n print(f\"Received request: {request.path}\")\n return handler(request, *args, **kwargs)\n return wrapper\n\nrouter.add_route(\"/user/:id\", get_user, methods=[\"GET\"], middlewares=[log_request])\n```\n\n### HttpServer\n\nThe `HttpServer` class handles the low-level HTTP protocol details.\n\n**Key Features:**\n\n- **Request Handling:** Processes incoming HTTP requests.\n- **Response Sending:** Formats and sends HTTP responses.\n- **Connection Management:** Manages client connections asynchronously.\n\n**Usage:**\n\nThis class is usually managed internally by `AreionServer` and doesn't require direct interaction.\n\n## Default Component Implementation\n\nAreion provides default implementations for several core components that can be used out of the box. These components are designed to work together seamlessly and provide a solid foundation for building web applications. Feel free to use these default components or create your own custom implementations according to the interfaces in `areion/base`.\n\n### Orchestrator\n\nThe `Orchestrator` class manages background tasks and scheduling. The startup and shutdown are managed by the `AerionServer`.\n\n**Key Features:**\n\n- **Task Submission:** Allows submitting tasks to be executed asynchronously.\n- **Scheduling:** Supports scheduling tasks using cron expressions.\n- **Thread Management:** Uses a thread pool for concurrent execution.\n\n**Usage:**\n\n```python\nfrom areion import DefaultOrchestrator\n\norchestrator = DefaultOrchestrator(max_workers=4)\n\ndef background_task():\n print(\"Running background task\")\n\n# Submit a task\norchestrator.submit_task(background_task)\n\n# Schedule a cron task\norchestrator.schedule_cron_task(background_task, {'hour': '*/1'})\n```\n\n### Logger\n\nThe `Logger` class provides logging capabilities. This logger is passed to multiple other components and also injected into each HttpRequest that is accesible in every route handler.\n\n**Key Features:**\n\n- **Configurable Levels:** Supports standard logging levels (INFO, DEBUG, ERROR, etc.).\n- **File and Console Logging:** Can log to both files and the console.\n- **Formatter Support:** Customizable log formatting.\n\n**Usage:**\n\n```python\nfrom areion import DefaultLogger, AreionServerBuilder, DefaultRouter\n\nrouter = DefaultRouter()\nlogger = DefaultLogger(log_file=\"server.log\", log_level=\"INFO\")\n\n@router.route(\"/log\", methods=[\"GET\"])\ndef some_handler(request):\n logger.info(\"Processing request\")\n return \"Response\"\n\nserver = AreionServerBuilder().with_router(router).with_logger(logger).build()\n```\n\n### Engine\n\nThe `Engine` class handles template rendering.\n\n**Key Features:**\n\n**Jinja2 Integration:** Uses Jinja2 for template rendering.\n**Template Directory:** Configurable template directory.\n\n**Usage:**\n\n```python\nfrom areion import DefaultEngine\n\nengine = Engine(templates_dir=\"templates\")\n\n# Rendering a template\ndef home(request):\n context = {\"title\": \"Home\"}\n return request.render_template(\"home.html\", context)\n```\n\n## Advanced Usage\n\n### Middleware\n\nMiddleware functions allow you to process requests and responses globally or for specific routes.\n\n**Creating Middleware:**\n\n```python\ndef auth_middleware(handler):\n def wrapper(request, *args, **kwargs):\n if not request.get_header(\"Authorization\"):\n return HttpResponse(status_code=401, body=\"Unauthorized\")\n return handler(request, *args, **kwargs)\n return wrapper\n```\n\n**Applying Middleware:**\n\n**Global Middleware:**\n\n```python\nrouter.add_global_middleware(auth_middleware)\n```\n\n**Route-specific Middleware:**\n\n```python\n@router.route(\"/dashboard\", middlewares=[auth_middleware])\ndef dashboard(request):\n return \"Welcome to the dashboard\"\n```\n\n### Grouping Routes\n\nYou can group routes under a common path and apply middlewares to the group.\n\n**Usage:**\n\n```python\n# Define group-specific middleware\ndef group_middleware(handler):\n def wrapper(request, *args, **kwargs):\n print(\"Group middleware executed\")\n return handler(request, *args, **kwargs)\n return wrapper\n\n# Create a route group\napi_group = router.group(\"/api\", middlewares=[group_middleware])\n\n@api_group.route(\"/users\")\ndef api_users(request):\n return \"API Users\"\n\n@api_group.route(\"/posts\")\ndef api_posts(request):\n return \"API Posts\"\n```\n\n### Template Rendering\n\nUse the Engine component to render templates with dynamic content.\n\n**Usage:**\n\n```python\ndef profile(request):\n user_data = {\"name\": \"John Doe\", \"age\": 30}\n return request.render_template(\"profile.html\", user_data)\n```\n\n### Task Scheduling\n\nSchedule tasks to run at specified intervals using the Orchestrator.\n\n**Usage:**\n\n```python\ndef cleanup_task():\n print(\"Performing cleanup\")\n\n# Schedule to run every day at midnight\norchestrator.schedule_cron_task(cleanup_task, {'hour': '0', 'minute': '0'})\n```\n\n## API Reference\n\n### AreionServer API\n\n#### AreionServer\n\nRepresents the main server class.\n\n**Constructor Parameters:**\n\n- `host (str)`: Server host address.\n- `port (int)`: Server port number.\n- `router (Router)`: Router instance.\n- `orchestrator (Orchestrator, optional)`: Orchestrator instance.\n- `logger (Logger, optional)`: Logger instance.\n- `engine (Engine, optional)`: Template engine instance.\n- `static_dir (str, optional)`: Directory for static files.\n\n**Methods:**\n\n- `run()`: Starts the server synchronously.\n- `start()`: Starts the server asynchronously.\n- `stop()`: Initiates server shutdown.\n\n#### AreionServerBuilder\n\nBuilder class for constructing AreionServer instances.\n\n**Methods:**\n\n- `with_host(host)`: Sets the server host.\n- `with_port(port)`: Sets the server port.\n- `with_router(router)`: Sets the router.\n- `with_orchestrator(orchestrator)`: Sets the orchestrator.\n- `with_logger(logger)`: Sets the logger.\n- `with_engine(engine)`: Sets the template engine.\n- `with_static_dir(static_dir)`: Sets the static directory.\n- `with_development_mode(bool)`: Enables development mode and Swagger UI/OpenAPI routes.\n- `build()`: Builds and returns an AreionServer instance.\n\n### Router API\n\n#### Router\n\nManages URL routes and their handlers.\n\n**Methods:**\n\n- `add_route(path, handler, methods, middlewares)`: Adds a route.\n- `route(path, methods, middlewares)`: A decorator to define a route with optional middlewares.\n- `include_router(router)`: Includes all routes from the given sub-router into the current router.\n- `group(base_path, middlewares)`: Creates a sub-router with a base path and optional group-specific middlewares.\n- `add_global_middleware(middleware)`: Adds a middleware that will be applied globally to all routes.\n- `get_handler(method, path)`: Retrieves the handler for a given path and method.\n- `get_allowed_methods(path)`: Retrieves the allowed methods for a given path.\n\n### HttpRequest and HttpResponse\n\n#### HttpRequest\n\nRepresents an HTTP request. These are injected into each route handler as the first argument via the HttpServer.\n\n**Attributes:**\n\n- `method (str)`: HTTP method.\n- `path (str)`: Request path.\n- `headers (dict)`: Request headers.\n- `metadata (dict)`: Additional metadata.\n- `body (str)`: Request body.\n- `path (str)`: Request path.\n- `query_params (dict)`: Query parameters.\n\n**Methods:**\n\n- `add_header(key, value)`: Adds a header.\n- `get_header(key)`: Retrieves a header value.\n- `get_parsed_body()`: Retrieves the request body as a dictionary.\n- `get_raw_body()`: Retrieves the raw request body.\n- `get_query_param(key)`: Retrieves a query parameter.\n- `get_raw_query_params()`: Retrieves the raw query parameters.\n- `get_parsed_query_params()`: Retrieves the query parameters as a dictionary.\n- `add_metadata(key, value)`: Adds metadata.\n- `get_metadata(key)`: Retrieves metadata.\n- `render_template(template_name, context)`: Renders a template.\n- `submit_task(task, *args)`: Submits a task to the orchestrator.\n- `log(message, level)`: Logs a message.\n- `as_dict()`: Converts the request to a dictionary.\n\n#### HttpResponse\n\nRepresents an HTTP response.\n\n**Constructor Parameters:**\n\n- `body (any)`: Response body.\n- `status_code (int)`: HTTP status code.\n- `content_type (str, optional)`: Content type.\n- `headers (dict, optional)`: Additional headers.\n\n**Methods:**\n\n- `format_response()`: Formats the response for sending.\n- `set_header(key, value)`: Sets a header.\n- `set_headers(headers)`: Sets multiple headers.\n- `set_status_code(status_code)`: Sets the status code.\n\n#### Response Utility Functions\n\n- `create_file_response(file_path: str, status_code: int = 200)`: Creates a response for a file given a filepath.\n- `create_json_response(data: dict, status_code: int = 200)`: Creates a JSON response.\n- `create_text_response(text: str, status_code: int = 200)`: Creates a text response.\n- `create_html_response(html: str, status_code: int = 200)`: Creates an HTML response.\n- `create_redirect_response(location: str, status_code: int = 302)`: Creates a redirect response.\n- `create_error_response(status_code: int, message: str = None, headers: dict = None)`: Creates an error response.\n- `create_empty_response(status_code: int = 204, headers: dict = None)`: Creates an empty response.\n\n## Exception Handling\n\nAreion provides custom exceptions for common HTTP errors. These exceptions can be raised in route handlers to return the corresponding error response and status code.\n\n- `HttpError`: Base class for HTTP errors.\n- `BadRequestError`: Corresponds to 400 Bad Request.\n- `UnauthorizedError`: Corresponds to 401 Unauthorized.\n- `ForbiddenError`: Corresponds to 403 Forbidden.\n- `NotFoundError`: Corresponds to 404 Not Found.\n- `MethodNotAllowedError`: Corresponds to 405 Method Not Allowed.\n- `InternalServerError`: Corresponds to 500 Internal Server Error.\n\n**Easily create custom exceptions by subclassing the HttpError class.**\n\n**Usage:**\n\n```python\nfrom areion import NotFoundError\n\ndef get_item(request, item_id):\n item = database.get(item_id)\n if not item:\n raise NotFoundError(\"Item not found\")\n return item\n```\n\n_Exceptions in routes and middleware are handled globally and converted to a proper HTTP response._\n\n## Best Practices\n\n### Responses\n\nWe recommend returning a `HttpResponse` object directly from route handlers. This allows for more control over the response status code, headers, and body. Additionally, it is recommended, but not required, to pass an explicit `content_type` during construction for performance reasons.\n\n_Helpful wrappers now exist in the `areion/utils/response_utils.py` to make this easier for common use cases._\n\n_Make sure that objects are JSON serializable before returning them in the response body._\n\n**Example:**\n\n```python\nfrom areion import HttpResponse\n\n@router.route(\"/user\", methods=GET)\ndef get_user(request):\n user = {\n \"name\": \"John Doe\",\n \"age\": 30\n }\n return HttpResponse(body=user, content_type=\"application/json\")\n```\n\n## Missing HTTP/1.1 Features\n\n- **Chunked Transfer Encoding:** Areion does not support chunked transfer encoding yet.\n- **Compression:** Areion does not support compression yet.\n- **Caching:** Areion does not support caching yet.\n- **Cookies:** Areion does not support cookies yet.\n- **Range Requests:** Areion does not support range requests yet.\n\n## Contributing\n\nContributions are welcome! For feature requests, bug reports, or questions, please open an issue. If you would like to contribute code, please open a pull request with your changes.\n\n## License\n\nMIT License\n\nCopyright (c) 2024 Joshua Caponigro\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software.\n\n[pypi-shield]: https://img.shields.io/pypi/pyversions/areion?color=281158\n[pypi-url]: https://pypi.org/project/areion/\n[pypiversion-shield]: https://img.shields.io/pypi/v/areion?color=361776\n[license-url]: https://github.com/JoshCap20/areion/blob/main/LICENSE\n[license-shield]: https://img.shields.io/github/license/joshcap20/areion\n",
"bugtrack_url": null,
"license": "Copyright (c) 2024 Joshua Caponigro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u201cSoftware\u201d), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \u201cAS IS\u201d, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"summary": "A lightweight, fast, and extensible asynchronous Python web server framework.",
"version": "1.1.11",
"project_urls": {
"Documentation": "https://github.com/JoshCap20/areion/blob/main/README.md",
"Homepage": "https://github.com/JoshCap20/areion",
"Issues": "https://github.com/JoshCap20/areion/issues",
"Repository": "https://github.com/JoshCap20/areion"
},
"split_keywords": [
"python",
" api",
" framework",
" web",
" web-framework",
" http-server"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2cbf95eddd3d8a122859a9191bd3176abb36146814858b557233e9a715830395",
"md5": "3e09d79e4a6d0419a1bfc01414b4f81a",
"sha256": "942f98dbf304c4c080378daf9deb5939c0dea3136a1d645cde0d1b5b7092470a"
},
"downloads": -1,
"filename": "areion-1.1.11-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3e09d79e4a6d0419a1bfc01414b4f81a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 53217,
"upload_time": "2024-10-12T20:14:20",
"upload_time_iso_8601": "2024-10-12T20:14:20.929479Z",
"url": "https://files.pythonhosted.org/packages/2c/bf/95eddd3d8a122859a9191bd3176abb36146814858b557233e9a715830395/areion-1.1.11-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0e66627562dd62b6b1ab49122510e825c54d04e98894a4ada3fe07710c0ac5bf",
"md5": "69dddb45b8b1aa70cbbf8675fdf4b1a1",
"sha256": "d41180225c789786a1b264c63a5cbd3676b662796c32abefb9706ed2a41d9ff9"
},
"downloads": -1,
"filename": "areion-1.1.11.tar.gz",
"has_sig": false,
"md5_digest": "69dddb45b8b1aa70cbbf8675fdf4b1a1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 50125,
"upload_time": "2024-10-12T20:14:23",
"upload_time_iso_8601": "2024-10-12T20:14:23.370691Z",
"url": "https://files.pythonhosted.org/packages/0e/66/627562dd62b6b1ab49122510e825c54d04e98894a4ada3fe07710c0ac5bf/areion-1.1.11.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-12 20:14:23",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "JoshCap20",
"github_project": "areion",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "apscheduler",
"specs": [
[
">=",
"3.0.0"
]
]
},
{
"name": "jinja2",
"specs": [
[
">=",
"3.0.0"
]
]
},
{
"name": "orjson",
"specs": [
[
">=",
"3.0.0"
]
]
},
{
"name": "uvloop",
"specs": [
[
">=",
"0.20.0"
]
]
},
{
"name": "httptools",
"specs": [
[
">=",
"0.6.1"
]
]
}
],
"lcname": "areion"
}