ASGI Application Mounting (In-Process)
The asgi extension mounts ASGI and WSGI applications directly in the pyserve process.
This is simpler and has lower latency, but all apps share the same process.
Overview
The ASGI mounting system provides:
- Multi-framework support — Mount FastAPI, Flask, Django, Starlette, or custom ASGI apps
- Path-based routing — Each app handles requests at its mounted path
- WSGI compatibility — Automatic WSGI-to-ASGI conversion for Flask/Django
- Factory pattern support — Create apps dynamically with arguments
- Path stripping — Optionally strip mount path from requests
Configuration
ASGI applications are mounted via the asgi extension:
extensions: - type: asgi config: mounts: - path: "/api" app_path: "myapp.api:app" app_type: asgi name: "api-app" strip_path: true
Mount Configuration Options
- path
- URL path where the application will be mounted. Example:
/api - app_path
- Python import path to the application. Format:
module.submodule:attribute - app_type
- Application type:
asgiorwsgi. Default:asgi - module_path
- Optional path to add to
sys.pathfor module resolution - factory
- If
true,app_pathpoints to a factory function. Default:false - factory_args
- Dictionary of arguments to pass to the factory function
- name
- Friendly name for logging. Default: uses
app_path - strip_path
- Remove mount path from request URL. Default:
true
Mounting FastAPI
FastAPI applications are native ASGI:
# myapp/api.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/users")
async def get_users():
return [{"id": 1, "name": "Alice"}]
extensions: - type: asgi config: mounts: - path: "/api" app_path: "myapp.api:app" app_type: asgi name: "fastapi-app"
With this configuration:
GET /api/users→ handled by FastAPI asGET /users- FastAPI docs available at
/api/docs
Mounting Flask
Flask applications are WSGI and will be automatically wrapped:
# myapp/flask_api.py
from flask import Flask
app = Flask(__name__)
@app.route("/hello")
def hello():
return {"message": "Hello from Flask!"}
extensions: - type: asgi config: mounts: - path: "/flask" app_path: "myapp.flask_api:app" app_type: wsgi name: "flask-app"
a2wsgi or asgiref
to be installed. Install with: pip install a2wsgi
Mounting Django
Django can be mounted using its ASGI application:
extensions: - type: asgi config: mounts: - path: "/django" django_settings: "myproject.settings" module_path: "/path/to/django/project" name: "django-app"
Factory Pattern
Use factory functions to create apps with custom configuration:
# myapp/api.py
from fastapi import FastAPI
def create_app(debug: bool = False, prefix: str = "/v1") -> FastAPI:
app = FastAPI(debug=debug)
@app.get(f"{prefix}/status")
async def status():
return {"debug": debug}
return app
extensions: - type: asgi config: mounts: - path: "/api" app_path: "myapp.api:create_app" app_type: asgi factory: true factory_args: debug: true prefix: "/v2"
Path Stripping
By default, strip_path: true removes the mount prefix from requests:
| Request | strip_path: true |
strip_path: false |
GET /api/users |
App sees /users |
App sees /api/users |
GET /api/ |
App sees / |
App sees /api/ |
Multiple Mounts
Mount multiple applications at different paths:
extensions: - type: asgi config: mounts: # FastAPI for REST API - path: "/api" app_path: "apps.api:app" app_type: asgi # Flask admin panel - path: "/admin" app_path: "apps.admin:app" app_type: wsgi # Starlette websocket handler - path: "/ws" app_path: "apps.websocket:app" app_type: asgi # Standard routing for static files - type: routing config: regex_locations: "__default__": root: "./static"
Mount Priority
Mounts are matched by path length (longest first). Given mounts at
/api and /api/v2:
/api/v2/users→ matches/api/v2mount/api/users→ matches/apimount
Combining with Routing
ASGI mounts work alongside the routing extension. The asgi extension
should be listed before routing to handle mounted paths first:
extensions: # ASGI apps handle /api/* and /admin/* - type: asgi config: mounts: - path: "/api" app_path: "myapp:api" app_type: asgi # Routing handles everything else - type: routing config: regex_locations: "=/health": return: "200 OK" "__default__": spa_fallback: true root: "./dist"
Python API
For programmatic mounting, see ASGI Mount API Reference.