starlette/docs/third-party-packages.md

8.5 KiB

Starlette has a rapidly growing community of developers, building tools that integrate into Starlette, tools that depend on Starlette, etc.

Here are some of those third party packages:

Plugins

Starlette APISpec

Github

Easy APISpec integration for Starlette.

Document your REST API built with Starlette by declaring OpenAPI (Swagger) schemas in YAML format in your endpoints' docstrings.

Starlette API

Github

That library aims to bring a layer on top of Starlette framework to provide useful mechanism for building APIs. It's based on API Star, inheriting some nice ideas like:

  • Schema system based on Marshmallow that allows to declare the inputs and outputs of endpoints and provides a reliable way of validate data against those schemas.
  • Dependency Injection that ease the process of managing parameters needed in endpoints.
  • Components as the base of the plugin ecosystem, allowing you to create custom or use those already defined in your endpoints, injected as parameters.
  • Starlette ASGI objects like Request, Response, Session and so on are defined as components and ready to be injected in your endpoints.
  • Auto generated API schema using OpenAPI standard. It uses the schema system of your endpoints to extract all the necessary information to generate your API Schema.
  • Auto generated docs providing a Swagger UI or ReDocs endpoint.
from marshmallow import Schema, fields, validate
from starlette_api.applications import Starlette


# Data Schema
class Puppy(Schema):
    id = fields.Integer()
    name = fields.String()
    age = fields.Integer(validate=validate.Range(min=0))


# Database
puppies = [
    {"id": 1, "name": "Canna", "age": 6},
    {"id": 2, "name": "Sandy", "age": 12},
]


# Application
app = Starlette(
    components=[],      # Without custom components
    title="Foo",        # API title
    version="0.1",      # API version
    description="Bar",  # API description
    schema="/schema/",  # Path to expose OpenAPI schema
    docs="/docs/",      # Path to expose Swagger UI docs
    redoc="/redoc/",    # Path to expose ReDoc docs
)


# Views
@app.route("/", methods=["GET"])
def list_puppies(name: str = None) -> Puppy(many=True):
    """
    List the puppies collection. There is an optional query parameter that
    specifies a name for filtering the collection based on it.

    Request example:
    GET http://example.com/?name=Sandy

    Response example:
    200
    [
        {"id": 2, "name": "Sandy", "age": 12}
    ]
    """
    return [puppy for puppy in puppies if puppy["name"] == name]

webargs-starlette

Github

Declarative request parsing and validation for Starlette, built on top of webargs.

Allows you to parse querystring, JSON, form, headers, and cookies using type annotations.

import uvicorn
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from webargs_starlette import use_annotations

app = Starlette()


@app.route("/")
@use_annotations(locations=("query",))
async def index(request, name: str = "World"):
    return JSONResponse({"Hello": name})


if __name__ == "__main__":
    uvicorn.run(app, port=5000)

# curl 'http://localhost:5000/'
# {"Hello": "World"}
# curl 'http://localhost:5000/?name=Ada'
# {"Hello": "Ada"}

Mangum

Github

Serverless ASGI adapter for AWS Lambda & API Gateway.

from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from mangum import Mangum


app = Starlette()


@app.route("/")
def homepage(request):
    return PlainTextResponse("Hello, world!")


handler = Mangum(app)  # optionally set debug=True

Nejma

Github

Helps you manage and send messages to groups of channels.


from nejma.ext.starlette import WebSocketEndpoint

@app.websocket_route("/ws")
class Chat(WebSocketEndpoint):
    encoding = "json"

    async def on_receive(self, websocket, data):
        room_id = data['room_id']
        message = data['message']
        username = data['username']

        if message.strip():
            group = f"group_{room_id}"

            self.channel_layer.add(group, self.channel)

            payload = {
                "username": username,
                "message": message,
                "room_id": room_id
            }
            await self.channel_layer.group_send(group, payload)

Checkout nejma-chat, a simple chat application built using nejma and starlette.

Frameworks

Responder

Github | Documentation

A familiar HTTP Service Framework for Python.

  • Flask-style route expression, with new capabilities -- all while using Python 3.6+'s new f-string syntax.
  • Falcon's "every request and response is passed into to each view and mutated" methodology.
  • Support for YAML by default.
  • Several of Starlette's optional dependencies pre-installed, like:
    • Production static file server.
    • Uvicorn server.
    • GraphQL support, via Graphene.
import responder

api = responder.API()

@api.route("/{greeting}")
async def greet_world(req, resp, *, greeting):
    resp.text = f"{greeting}, world!"

if __name__ == '__main__':
    api.run()

FastAPI

Github | Documentation

High performance, easy to learn, fast to code, ready for production.

An API framework inspired by APIStar's previous server system with type declarations for route parameters, based on the OpenAPI specification version 3.0.0+ (with JSON Schema), powered by Pydantic for the data handling.

Use standard Python 3.6+ types as parameters to get:

  • Autocomplete everywhere.
  • Data conversion.
  • Data validation.
  • Automatic documentation with OpenAPI (and JSON Schema), based on the same Python types.

Includes:

  • A simple but powerful dependency injection system.
  • Automatic interactive documentation (based on Swagger UI and ReDoc).
  • Security utilities, including OAuth2 with JWT tokens.
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

This code declares a path /, and a path /items/{item_id}.

The path for /items/{item_id} has:

  • A path parameter item_id that will be validated as an int, with automatic errors when invalid.
  • An optional (by default None) query parameter q of type str.

Calling http://example.com/items/2?q=myquery will return:

{"item_id": 2, "q": "myquery"}

The same way you can declare JSON body schemas, headers, etc.

Bocadillo

Github | Documentation

A modern Python web framework filled with asynchronous salsa.

Bocadillo is async-first and designed with productivity and simplicity in mind. It is not meant to be minimal: a carefully chosen set of included batteries helps you build performant web apps and services with minimal setup.

Key features include:

  • Simple, powerful and familiar views and routing, inspired by the greatest (Flask, Falcon).
  • First-class support for both HTTP / REST and WebSocket.
  • Built-in CORS, HSTS, GZip, HTTP streaming, Jinja2 templates, background tasks, static files…

… and more ahead, as depicted in the Roadmap.

The example below demonstrates a simple WebSocket echo server.

from bocadillo import API, WebSocket

api = API()

@api.websocket_route("/echo")
async def echo(ws: WebSocket):
    async with ws:
        async for message in ws:
            await ws.send(message)

if __name__ == "__main__":
    api.run()