Skip to main content

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

Project description

Areion

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.

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

Uploaded Source

Built Distribution

areion-1.0.0-py3-none-any.whl (26.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for areion-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a5509b19931d9c90117532b4b49ca667354a06d140742eb1a2213ad142e90bd9
MD5 1bdca930445ea5c62d99d01041290428
BLAKE2b-256 1f3051e15f33dd477c1c0c99716eb5d074e6657d100db647e63896ac8c860212

See more details on using hashes here.

File details

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

File metadata

  • Download URL: areion-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 26.6 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.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87af7b7580bbecca137942b00ba443f9f6474c4c6a6e90fb3bc6647d7effeef2
MD5 27f5181f7be43d64b64cc09258e1c189
BLAKE2b-256 45ee5d40c1f54e59250241fccde937f5545ac891019d808b6bd5ff63d38f5daf

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