docs.pyserve.org/reference/asgi-mount.html
Илья Глазунов 00119ce463
All checks were successful
Deploy to Production / deploy (push) Successful in 5s
Refactor documentation for reverse proxy and routing guides
2025-12-08 01:05:52 +03:00

255 lines
8.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ASGI Mount API - pyserve</title>
<link rel="stylesheet" href="../style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
</head>
<body>
<div id="container">
<div id="header">
<h1>pyserve</h1>
<div class="tagline">python application orchestrator</div>
</div>
<div class="breadcrumb">
<a href="../index.html">Home</a> / <a href="index.html">Reference</a> / ASGI Mount API
</div>
<div id="content">
<h2>ASGI Mount API Reference</h2>
<p>The <code>pyserve.asgi_mount</code> module provides a Python API for mounting
ASGI and WSGI applications programmatically.</p>
<h3>Classes</h3>
<h4>ASGIAppLoader</h4>
<p>Loads and manages ASGI/WSGI applications from Python import paths.</p>
<pre><code class="language-python">from pyserve import ASGIAppLoader
loader = ASGIAppLoader()
# Load an ASGI app
app = loader.load_app(
app_path="mymodule:app",
app_type="asgi",
module_path="/path/to/project",
factory=False,
factory_args=None
)</code></pre>
<h5>Methods</h5>
<dl>
<dt>load_app(app_path, app_type="asgi", module_path=None, factory=False, factory_args=None)</dt>
<dd>
Load an application from an import path.
<ul class="indent">
<li><code>app_path</code>: Import path in format <code>module:attribute</code></li>
<li><code>app_type</code>: <code>"asgi"</code> or <code>"wsgi"</code></li>
<li><code>module_path</code>: Optional path to add to <code>sys.path</code></li>
<li><code>factory</code>: If True, call the attribute as a factory function</li>
<li><code>factory_args</code>: Dict of arguments for factory function</li>
</ul>
Returns the loaded ASGI application or <code>None</code> on error.
</dd>
<dt>get_app(app_path)</dt>
<dd>Get a previously loaded application by its path.</dd>
<dt>reload_app(app_path, **kwargs)</dt>
<dd>Reload an application, useful for development hot-reloading.</dd>
</dl>
<h4>MountedApp</h4>
<p>Represents an application mounted at a specific path.</p>
<pre><code class="language-python">from pyserve import MountedApp
mount = MountedApp(
path="/api",
app=my_asgi_app,
name="my-api",
strip_path=True
)</code></pre>
<h5>Attributes</h5>
<dl>
<dt>path: str</dt>
<dd>The mount path (without trailing slash).</dd>
<dt>app: ASGIApp</dt>
<dd>The ASGI application.</dd>
<dt>name: str</dt>
<dd>Friendly name for logging.</dd>
<dt>strip_path: bool</dt>
<dd>Whether to strip the mount path from requests.</dd>
</dl>
<h5>Methods</h5>
<dl>
<dt>matches(request_path) → bool</dt>
<dd>Check if a request path matches this mount.</dd>
<dt>get_modified_path(original_path) → str</dt>
<dd>Get the modified path after stripping mount prefix.</dd>
</dl>
<h4>ASGIMountManager</h4>
<p>Manages multiple mounted applications and routes requests.</p>
<pre><code class="language-python">from pyserve import ASGIMountManager
manager = ASGIMountManager()
# Mount using app instance
manager.mount(path="/api", app=my_app)
# Mount using import path
manager.mount(
path="/flask",
app_path="myapp:flask_app",
app_type="wsgi"
)</code></pre>
<h5>Methods</h5>
<dl>
<dt>mount(path, app=None, app_path=None, app_type="asgi", module_path=None, factory=False, factory_args=None, name="", strip_path=True) → bool</dt>
<dd>
Mount an application at a path. Either <code>app</code> or <code>app_path</code> must be provided.
Returns <code>True</code> on success.
</dd>
<dt>unmount(path) → bool</dt>
<dd>Remove a mounted application. Returns <code>True</code> if found and removed.</dd>
<dt>get_mount(request_path) → Optional[MountedApp]</dt>
<dd>Get the mount that matches a request path.</dd>
<dt>handle_request(scope, receive, send) → bool</dt>
<dd>Handle an ASGI request. Returns <code>True</code> if handled by a mounted app.</dd>
<dt>list_mounts() → List[Dict]</dt>
<dd>Get a list of all mounts with their configuration.</dd>
</dl>
<h5>Properties</h5>
<dl>
<dt>mounts: List[MountedApp]</dt>
<dd>Copy of the current mounts list (sorted by path length, longest first).</dd>
</dl>
<h3>Helper Functions</h3>
<p>Convenience functions for loading specific framework applications:</p>
<h4>create_fastapi_app()</h4>
<pre><code class="language-python">from pyserve import create_fastapi_app
app = create_fastapi_app(
app_path="myapp.api:app",
module_path=None,
factory=False,
factory_args=None
)</code></pre>
<h4>create_flask_app()</h4>
<pre><code class="language-python">from pyserve import create_flask_app
app = create_flask_app(
app_path="myapp.web:app",
module_path=None,
factory=False,
factory_args=None
)</code></pre>
<p>Automatically wraps the WSGI app for ASGI compatibility.</p>
<h4>create_django_app()</h4>
<pre><code class="language-python">from pyserve import create_django_app
app = create_django_app(
settings_module="myproject.settings",
module_path="/path/to/project"
)</code></pre>
<p>Sets <code>DJANGO_SETTINGS_MODULE</code> and returns Django's ASGI application.</p>
<h4>create_starlette_app()</h4>
<pre><code class="language-python">from pyserve import create_starlette_app
app = create_starlette_app(
app_path="myapp:starlette_app",
module_path=None,
factory=False,
factory_args=None
)</code></pre>
<h3>Usage Example</h3>
<p>Complete example mounting multiple applications:</p>
<pre><code class="language-python">from pyserve import (
PyServeServer,
ASGIMountManager,
create_fastapi_app,
create_flask_app
)
# Create mount manager
mounts = ASGIMountManager()
# Mount FastAPI
api_app = create_fastapi_app("myapp.api:app")
if api_app:
mounts.mount("/api", app=api_app, name="api")
# Mount Flask
admin_app = create_flask_app("myapp.admin:app")
if admin_app:
mounts.mount("/admin", app=admin_app, name="admin")
# List mounts
for mount in mounts.list_mounts():
print(f"Mounted {mount['name']} at {mount['path']}")</code></pre>
<h3>Error Handling</h3>
<p>All loader functions return <code>None</code> on failure and log errors.
Check the return value before using:</p>
<pre><code class="language-bash">app = create_fastapi_app("nonexistent:app")
if app is None:
# Handle error - check logs for details
print("Failed to load application")</code></pre>
<h3>WSGI Compatibility</h3>
<p>For WSGI applications, pyserve uses adapters in this priority:</p>
<ol class="indent">
<li><code>a2wsgi.WSGIMiddleware</code> (recommended)</li>
<li><code>asgiref.wsgi.WsgiToAsgi</code> (fallback)</li>
</ol>
<p>Install an adapter:</p>
<pre><code class="language-bash">pip install a2wsgi # recommended
# or
pip install asgiref</code></pre>
<div class="note">
<strong>See Also:</strong>
<ul class="indent">
<li><a href="../guides/asgi-mount.html">ASGI Mounting Guide</a> — Configuration-based mounting</li>
<li><a href="extensions.html">Extensions</a> — ASGI extension configuration</li>
</ul>
</div>
</div>
<div id="footer">
<p>pyserve &copy; 2024-2025 | MIT License</p>
</div>
</div>
</body>
</html>