Skip to main content

A lightweight, fast, and extensible asynchronous Python web server framework.

Project description

Areion Server

PyPi PyPi License

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.

Benchmark

We conducted performance benchmarks to compare Areion with FastAPI, focusing on throughput and latency under high-load conditions. The goal was to evaluate Areion'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

Areion

Running 30s test @ http://localhost:8000/json
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     7.15ms    1.34ms  38.99ms   97.58%
    Req/Sec     4.66k   336.44     8.89k    92.00%
  1,668,675 requests in 30.03s, 157.53MB read
  Socket errors: connect 0, read 2,622, write 0, timeout 0
  Non-2xx or 3xx responses: 1,980
Requests/sec:  55,566.74
Transfer/sec:      5.25MB

FastAPI

Running 30s test @ http://localhost:8000/json
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    73.42ms   10.92ms 190.27ms   89.45%
    Req/Sec   450.92     71.28   653.00     73.33%
  161,989 requests in 30.10s, 23.48MB read
  Socket errors: connect 0, read 418, write 0, timeout 0
Requests/sec:   5,381.16
Transfer/sec:    798.78KB

Analysis

Throughput (Requests per Second)

Areion: 55,566.74 requests/sec
FastAPI: 5,381.16 requests/sec
Areion handled approximately 10 times more requests per second than FastAPI.

Average Latency

Areion: 7.15 ms
FastAPI: 73.42 ms
Areion's average latency is about 10 times lower than FastAPI's, indicating faster response times.

Total Requests Handled

Areion: 1,668,675 requests
FastAPI: 161,989 requests
Areion processed significantly more total requests during the test duration.

Socket Errors

Areion: 2,622 read errors
FastAPI: 418 read errors
Areion encountered more socket read errors due to the higher number of connections and requests.

Table of Contents


Getting Started

Installation

Areion can be installed via pip:

pip install areion

Quick Start Guide

Below is a simple example to get you started with Areion.

from areion import AreionServerBuilder, DefaultRouter

# Initialize the router
router = DefaultRouter()

# Define a simple route
@router.route("/hello")
def hello_world(request):
    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:

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.

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.

Usage:

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)

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:

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:

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:

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:

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:

router.add_global_middleware(auth_middleware)

Route-specific Middleware:

@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:

# 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:

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:

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): Decorator for adding routes.
  • group(base_path, middlewares): Creates a sub-router (group).
  • add_global_middleware(middleware): Adds a global middleware.
  • get_handler(method, path): Retrieves the handler for a given path and method.

HttpRequest and HttpResponse

HttpRequest

Represents an HTTP request.

Attributes:

  • method (str): HTTP method.
  • path (str): Request path.
  • headers (dict): Request headers.
  • metadata (dict): Additional metadata.

Methods:

  • add_header(key, value): Adds a header.
  • get_header(key): Retrieves a header value.
  • 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.

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.

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:

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.

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

areion-1.1.2.tar.gz (35.7 kB view details)

Uploaded Source

Built Distribution

areion-1.1.2-py3-none-any.whl (39.3 kB view details)

Uploaded Python 3

File details

Details for the file areion-1.1.2.tar.gz.

File metadata

  • Download URL: areion-1.1.2.tar.gz
  • Upload date:
  • Size: 35.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.20

File hashes

Hashes for areion-1.1.2.tar.gz
Algorithm Hash digest
SHA256 83e7a53c30138e0866639bd455593d29ffa5f84647bec288e81e2970cf272431
MD5 d894c5f7effb08ad1eb6a722e68b1586
BLAKE2b-256 d947a99e17b1d3adfaecc93432aef391729eba18d396abe9cf93e60d9f658959

See more details on using hashes here.

File details

Details for the file areion-1.1.2-py3-none-any.whl.

File metadata

  • Download URL: areion-1.1.2-py3-none-any.whl
  • Upload date:
  • Size: 39.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.20

File hashes

Hashes for areion-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e87d983ca3ac24eb1b1d2954b6990c7c67e14b51200a5883dc1ebfd1b96adccc
MD5 da239fad66362b045705460fa4b4a978
BLAKE2b-256 f07dec77c94e5cda08097d4a753cb7ba89191420f35997ea9d47d47b7c593a3b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page