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.

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

Uploaded Source

Built Distribution

areion-1.0.1-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: areion-1.0.1.tar.gz
  • Upload date:
  • Size: 25.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.0.1.tar.gz
Algorithm Hash digest
SHA256 8820e62fdaec8c92add22cd47a694206d4bf52ddbd1d148e4c86a2d8b331421f
MD5 dfc6695f838583d9ed122979160c5253
BLAKE2b-256 ccad339e35f38fc98af0c4bb142e262368938d268fa04c5c2e1dbbbe4ad6acb4

See more details on using hashes here.

File details

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

File metadata

  • Download URL: areion-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 29.4 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fc64fa6c56159268af2499c8a179a5b65856369b2446e70b59e1e061bcf8d029
MD5 01e5ad9cc0c9717308d3a78444be3007
BLAKE2b-256 0973fb2b9802f8ab2bcc96835077868f6c51253853e52909f7404d43dd292e6a

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