Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/localstack/rolo
A Python framework for building HTTP-based server applications
https://github.com/localstack/rolo
api asgi chain-of-responsibility framework http pipeline python rest server web wsgi
Last synced: about 5 hours ago
JSON representation
A Python framework for building HTTP-based server applications
- Host: GitHub
- URL: https://github.com/localstack/rolo
- Owner: localstack
- License: apache-2.0
- Created: 2024-01-06T18:31:06.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2024-10-21T21:33:10.000Z (17 days ago)
- Last Synced: 2024-10-22T15:43:26.635Z (16 days ago)
- Topics: api, asgi, chain-of-responsibility, framework, http, pipeline, python, rest, server, web, wsgi
- Language: Python
- Homepage: https://rolo.localstack.cloud/
- Size: 240 KB
- Stars: 11
- Watchers: 17
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Rolo HTTP: A Python framework for building HTTP-based server applications.# Rolo HTTP
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](https://github.com/pallets/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](https://en.wikipedia.org/wiki/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](https://werkzeug.palletsprojects.com/en/2.3.x/routing/), 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.```python
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/")
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:```python
import pydantic
from werkzeug import Request
from werkzeug.serving import run_simplefrom 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/", methods=["GET"])
def read_item(request: Request, item_id: int):
return {"item_id": item_id, "q": request.query_string}@route("/items/", 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.```python
from werkzeug import run_simplefrom rolo import Response
from rolo.gateway import Gateway, HandlerChain, RequestContext
from rolo.gateway.wsgi import WsgiGatewaydef 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:
```console
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