Skip to main content

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

Project description

Areion

PyPi PyPi License

Areion is a lightweight, fast, and extensible Python web server framework. It 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.

Some say it is the simplest API ever. They might be right. To return a JSON response, you just return a dictionary. To return an HTML response, you just return a string. Return bytes for an octet-stream response. That's it.

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.

Only compatible with Python 3.10 and above.

Key Features

  • Simple API: Return dictionaries for JSON responses and strings for HTML responses.
  • Asynchronous Server: Supports asynchronous request handling with the asyncio library.
  • Multithreading: Orchestrate tasks using the orchestrator to manage multiple threads.
  • Routing: High-performance router supporting HTTP methods (GET, POST, PUT, DELETE) with method control at both route and group levels.
  • Orchestration: Orchestrator component for managing background tasks, job scheduling, and concurrent execution.
  • Templating: Render HTML templates using a customizable engine like Jinja2.
  • Builder Pattern: Use the builder pattern to cleanly configure your server before building it.
  • Extensibility: Add your own components to the server and easily extend its functionality.
  • Customizable: Every component is optional and can be replaced with your own implementation.

Installation

You can install Areion via pip:

pip install areion

Usage Example

Simple Usage

from areion import AreionServerBuilder, DefaultRouter, DefaultOrchestrator

router = DefaultRouter()
orchestrator = DefaultOrchestrator(max_workers=3)

# Dictionaries are automatically returned as JSON responses
@router.route("/")
def home_handler(request):
    return {"msg": "Hello from Areion Server"}

# Use the builder pattern to configure the server
server = (
    AreionServerBuilder()
    .with_orchestrator(orchestrator)
    .with_router(router)
    .with_port(8082)
    .build()
)

# Start the server (also starts the orchestrator and background tasks)
server.run()

Minimalist Usage

from areion import AreionServerBuilder, DefaultRouter

router = DefaultRouter()

def api_handler(request):
    return {"result": 5 + 2}

router.add_route("/api", api_handler)

server = AreionServerBuilder().with_router(router).build()

server.run()

In this example:

  • Builder Pattern: You configure the server with a builder before calling build() to instantiate it.
  • Asynchronous Server: The server is asynchronous, meaning it can handle concurrent requests using Python's asyncio.

The only required component is a router. This is because... it's a web server. You need to route requests to handlers. Everything else is optional.

Components

Orchestrator

The Orchestrator manages concurrent tasks, thread pools, and job scheduling. It helps run background jobs, task queues, or other non-blocking operations efficiently.

Orchestrator Demo

Below is an example demonstrating how to use the Orchestrator to schedule and manage tasks:

from areion import AreionServerBuilder, DefaultOrchestrator

def background_task(task_id):
    print(f"Running task {task_id}")
    return f"Task {task_id} completed."

# Initialize the orchestrator
router = DefaultRouter()
orchestrator = DefaultOrchestrator(max_workers=4)

# Submit tasks to the orchestrator
orchestrator.submit_task(background_task, "Task 1")
orchestrator.submit_task(background_task, "Task 2")

# Schedule a cron job to run every 10 seconds
orchestrator.schedule_cron_task(lambda: print("Scheduled task"), {"second": "*/10"})

# Build and start the server
server = AreionServerBuilder().with_router(router).with_orchestrator(orchestrator).build()
server.run()

Router

The Router is responsible for mapping incoming HTTP requests to their respective handler functions. You can define routes, group them, and specify allowed methods for each.

The Router also supports:

  • Route Groups (Sub-routers): Organize routes under common prefixes.
  • Route Decorators: Define routes more concisely using decorators.
  • Per-route Method Control: Specify allowed methods for each route or group.

Router Demo

Below is an example demonstrating how to use the Router to define routes, handlers, and engine rendering:

from areion import AreionServerBuilder, DefaultRouter

router = DefaultRouter()

@router.route("/", methods=["GET"])
def home_handler(request):
    return {"message": "Welcome to Areion"}

@router.route("/submit", methods=["POST"])
def submit_handler(request):
    return {"message": "Data submitted successfully"}

server = AreionServerBuilder().with_router(router).build()
server.run()

Sub-groups and Method Control

You can easily group routes together and define method restrictions for each group or individual route.

# Create API sub-router
api = router.group("/api", allowed_methods=["GET", "POST"])

@api.route("/message", methods=["GET"])
def api_message_handler(request):
    return {"message": "Hello from the API"}

@api.route("/submit", methods=["POST"])
def api_submit_handler(request):
    return {"message": "Data submitted successfully!"}
  • Sub-groups: Organize your routes under common prefixes using group().
  • Method Control: Specify allowed methods per route or group.

Simple API Demo

from areion import AreionServer, DefaultRouter

router = DefaultRouter()

# Can add any logic, assign tasks to the orchestrator (if defined)
@router.route("/", methods=["GET"])
def home_handler(request):
    return {"msg": "Hello from Areion Server", "version": "1.0", "status": "OK"}

@router.route("/about", methods=["GET"])
def about_handler(request):
    return {"msg": "About Areion Server", "version": "1.0", "status": "OK"}

@router.route("/contact", methods=["GET"])
def contact_handler(request):
    return {"msg": "Contact Areion Server", "version": "1.0", "status": "OK"}

# Initialize the server with the router
server = AreionServerBuilder().with_router(router)

# Start the server
server.start()

Logger

The Logger is a component that provides a structured logging system for the server. It allows you to log messages at different levels (DEBUG, INFO, WARN, ERROR) and provides a flexible way to customize the logging output. You can easily replace the default logger with your own implementation or add additional loggers to suit your needs.

Logger Demo

Below is an example demonstrating how to use the Logger to log messages at different levels:

from areion import AreionServerBuilder, DefaultRouter, DefaultLogger

router = DefaultRouter()

@router.route("/", methods=["GET"])
def home_handler(request):
    request.log("Home handler accessed", level="info")
    request.log(request.as_dict(), level="debug")
    return {"message": "Welcome to Areion"}

# Custom logger
logger = DefaultLogger(log_file="areion.log", log_level="DEBUG")

server = AreionServerBuilder().with_router(router).with_logger(logger).build()
server.run()

Engine

The Engine is responsible for rendering templates. By default, it supports Jinja2 and can be extended to support other template engines.

Engine Demo

Below is an example demonstrating how to use the Engine to render HTML templates with optional variables:

from areion import AreionServerBuilder, DefaultRouter, DefaultEngine
import os

# Filepath Definitions
base_dir = os.path.dirname(os.path.abspath(__file__))
template_dir = os.path.join(base_dir, "templates")

# Initialize the engine with the template directory
engine = DefaultEngine(templates_dir=template_dir)
router = DefaultRouter()

@router.route("/template", methods=["GET"])
def template_handler(request):
    return request.render_template("index.html", {"title": "Welcome", "message": "Hello from Areion"})

server = AreionServerBuilder().with_router(router).with_engine(engine).build()
server.run()

Custom Request and Response Handling

Each request object automatically gets injected with the server's logger, engine, and orchestrator. This allows you to perform tasks like template rendering, logging, and background task submission directly within request handlers.

Custom Request Example

from areion import AreionServerBuilder, DefaultRouter

router = DefaultRouter()

@router.route("/log", methods=["GET"])
def log_handler(request):
    request.log("Logging from the /log endpoint", level="info")
    return {"message": "Log entry added"}

@router.route("/background", methods=["GET"])
def background_handler(request):
    def task_to_run():
        print("Running background task")
        return "Task completed"

    request.submit_task(task_to_run)
    return {"message": "Background task submitted"}

server = AreionServerBuilder().with_router(router).build()
server.run()

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.0.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

areion-1.1.0-py3-none-any.whl (31.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: areion-1.1.0.tar.gz
  • Upload date:
  • Size: 27.8 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.0.tar.gz
Algorithm Hash digest
SHA256 831aff9a422c7aafe703352a5161cf544a6b811e3f4e269e964ecea3553316c2
MD5 77a5abb1983479d7f414fd3c69bae78f
BLAKE2b-256 0b931cfdc3178d6a14cc062b94cd7f7178be5685500d0f6cbbec09643f196ae0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: areion-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3f2afaf9e67daf7a264647f3f1b9f2358642617613d7638a9a7f368428ce6dcf
MD5 c42311a598cd2c405bf1343ac1fec927
BLAKE2b-256 16660ccef26e6e7e0e778f55c283560ecffdbf85eb3703ea83f0d0027f3257e3

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