Skip to main content

A Python framework for building HTTP-based server applications

Project description

Rolo HTTP

Rolo HTTP: A Python framework for building HTTP-based server applications.

Rolo HTTP

CI badge PyPI Version PyPI License Code style: black

Rolo is a flexible framework and library to build HTTP-based server applications beyond microservices and REST APIs. You can build HTTP-based RPC servers, websocket proxies, or other server types that typical web frameworks are not designed for.

Rolo extends Werkzeug, a flexible Python HTTP server library, for you to use concepts you are familiar with like Router, Request, Response, or @route. It introduces the concept of a Gateway and HandlerChain, an implementation variant of the chain-of-responsibility pattern.

Rolo is designed for environments that do not use asyncio, but still require asynchronous HTTP features like HTTP2 SSE or Websockets. To allow asynchronous communication, Rolo introduces an ASGI/WSGI bridge, that allows you to serve Rolo applications through ASGI servers like Hypercorn.

Usage

Default router example

Routers are based on Werkzeug's URL Map, but dispatch to handler functions directly. The @route decorator works similar to Flask or FastAPI, but they are not tied to an Application object. Instead, you can define routes on functions or methods, and then add them directly to the router.

from rolo import Router, route, Response
from werkzeug import Request
from werkzeug.serving import run_simple

@route("/users")
def user(_request: Request, args):
    assert not args
    return Response("user")

@route("/users/<int:user_id>")
def user_id(_request: Request, args):
    assert args
    return Response(f"{args['user_id']}")

router = Router()
router.add(user)
router.add(user_id)

# convert Router to a WSGI app and serve it through werkzeug
run_simple('localhost', 8080, router.wsgi(), use_reloader=True)

Pydantic integration

Routers use dispatchers to dispatch the request to functions. In the previous example, the default dispatcher calls the function with the Request object and the request arguments as dictionary. The "handler dispatcher" can transform functions into more Flask or FastAPI-like functions, that also allow you to integrate with Pydantic. Here's how the default example from the FastAPI documentation would look like with rolo:

import pydantic
from werkzeug import Request
from werkzeug.serving import run_simple

from rolo import Router, route


class Item(pydantic.BaseModel):
    name: str
    price: float
    is_offer: bool | None = None


@route("/", methods=["GET"])
def read_root(request: Request):
    return {"Hello": "World"}


@route("/items/<int:item_id>", methods=["GET"])
def read_item(request: Request, item_id: int):
    return {"item_id": item_id, "q": request.query_string}


@route("/items/<int:item_id>", methods=["PUT"])
def update_item(request: Request, item_id: int, item: Item):
    return {"item_name": item.name, "item_id": item_id}


router = Router()
router.add(read_root)
router.add(read_item)
router.add(update_item)

# convert Router to a WSGI app and serve it through werkzeug
run_simple("localhost", 8080, router.wsgi(), use_reloader=True)

Gateway & Handler Chain

A rolo Gateway holds a set of request, response, and exception handlers, as well as request finalizers. Gateway instances can then be served as WSGI or ASGI applications by using the appropriate serving adapter. Here is a simple example of a Gateway with just one handler that returns the URL and method that was invoked.

from werkzeug import run_simple

from rolo import Response
from rolo.gateway import Gateway, HandlerChain, RequestContext
from rolo.gateway.wsgi import WsgiGateway


def echo_handler(chain: HandlerChain, context: RequestContext, response: Response):
    response.status_code = 200
    response.set_json({"url": context.request.url, "method": context.request.method})


gateway = Gateway(request_handlers=[echo_handler])

app = WsgiGateway(gateway)
run_simple("localhost", 8080, app, use_reloader=True)

Serving this will yield:

curl http://localhost:8080/hello-world
{"url": "http://localhost:8080/hello-world", "method": "GET"}

Develop

Quickstart

to install the python and other developer requirements into a venv run:

make install

Format code

We use black and isort as code style tools. To execute them, run:

make format

Build distribution

To build a wheel and source distribution, simply run

make dist

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

rolo-0.8.1.tar.gz (74.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rolo-0.8.1-py3-none-any.whl (68.8 kB view details)

Uploaded Python 3

File details

Details for the file rolo-0.8.1.tar.gz.

File metadata

  • Download URL: rolo-0.8.1.tar.gz
  • Upload date:
  • Size: 74.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for rolo-0.8.1.tar.gz
Algorithm Hash digest
SHA256 0758ed8d6760beacf1bcc923c3bfef8bb441e68b49e4a031a779c528f1fdfb7e
MD5 4d1ad68973d60fd4d8054fa0747c39cd
BLAKE2b-256 ab43c8c2b1065355b6d544e1815667b71e44a6457aafbd76c325e2618c39cd30

See more details on using hashes here.

File details

Details for the file rolo-0.8.1-py3-none-any.whl.

File metadata

  • Download URL: rolo-0.8.1-py3-none-any.whl
  • Upload date:
  • Size: 68.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for rolo-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fb0c79fa86218fb096ecda671fe487c6e225b0875179e0bd670cd9bf33bb6bca
MD5 7025800f526c2d0ecc93ba532c4c58a6
BLAKE2b-256 3ebfd9357c7781bfaf7d051ecf15f07f870743d3f3c8316216b584f704b45eda

See more details on using hashes here.

Supported by

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