From 00119ce463ac6f54cde6b7932ed7e5c0e2f798ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=BB=D1=8C=D1=8F=20=D0=93=D0=BB=D0=B0=D0=B7=D1=83?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Mon, 8 Dec 2025 01:05:52 +0300 Subject: [PATCH] Refactor documentation for reverse proxy and routing guides --- README.md | 27 ++++- getting-started/installation.html | 20 ++-- getting-started/quickstart.html | 90 +++++++-------- guides/asgi-mount.html | 178 +++++++++++++++--------------- guides/configuration.html | 64 +++++------ guides/process-orchestration.html | 170 ++++++++++++++-------------- guides/reverse-proxy.html | 92 +++++++-------- guides/routing.html | 76 ++++++------- reference/asgi-mount.html | 126 ++++++++++----------- reference/cli.html | 32 +++--- reference/extensions.html | 148 ++++++++++++------------- style.css | 15 --- 12 files changed, 521 insertions(+), 517 deletions(-) diff --git a/README.md b/README.md index 68db5f7..70016ab 100644 --- a/README.md +++ b/README.md @@ -77,11 +77,30 @@ All documentation pages follow this structure: ## Code Highlighting -All pages include highlight.js for automatic syntax highlighting: +All pages use highlight.js for automatic syntax highlighting: -- CSS theme: `github-dark.min.css` (matches dark theme) -- Auto-initialization: `hljs.highlightAll()` -- Custom styles in `style.css` integrate with highlight.js +- **Theme**: `github-dark.min.css` (matches dark theme) +- **Auto-initialization**: `hljs.highlightAll()` runs on page load +- **Custom styles**: Enhanced color palette in `style.css` +- **Languages detected**: YAML, Bash, Python, Plaintext + +### Code Block Format + +All code blocks use semantic language classes: + +```html +

+server:
+  host: 0.0.0.0
+  port: 8080
+
+``` + +Supported languages: +- `language-yaml` — YAML configuration files +- `language-bash` — Shell commands and scripts +- `language-python` — Python code examples +- `language-plaintext` — Plain text output ## Deployment diff --git a/getting-started/installation.html b/getting-started/installation.html index 4dc1f09..09bdaaa 100644 --- a/getting-started/installation.html +++ b/getting-started/installation.html @@ -32,32 +32,32 @@

Install from Release (Recommended)

Download the latest wheel file from Git Releases and install it:

-
# Download the wheel file from releases
-# Example: pyserve-0.7.0-py3-none-any.whl
+        
# Download the wheel file from releases
+# Example: pyserve-0.7.0-py3-none-any.whl
 
-pip install pyserve-0.7.0-py3-none-any.whl
+pip install pyserve-0.7.0-py3-none-any.whl

After installation, the pyserve command will be available in your terminal:

-
pyserve --version
+
pyserve --version

Install from Source

For development or if you want the latest changes:

-
# Clone the repository
+        
# Clone the repository
 git clone https://github.com/ShiftyX1/PyServe.git
 cd PyServe
 
-# Install with Poetry (recommended for development)
+# Install with Poetry (recommended for development)
 make init
 
-# Or build and install the package
+# Or build and install the package
 make build
-pip install dist/pyserve-*.whl
+pip install dist/pyserve-*.whl

Verify Installation

Check that pyserve is installed correctly:

-
pyserve --version
-# Output: pyserve 0.7.0
+
pyserve --version
+# Output: pyserve 0.7.0

Dependencies

pyserve automatically installs the following dependencies:

diff --git a/getting-started/quickstart.html b/getting-started/quickstart.html index 422a00f..1e27a87 100644 --- a/getting-started/quickstart.html +++ b/getting-started/quickstart.html @@ -28,37 +28,37 @@

1. Create Configuration File

Create a file named config.yaml in your project directory:

-
http:
-  static_dir: ./static
-  templates_dir: ./templates
+        
http:
+  static_dir: ./static
+  templates_dir: ./templates
 
-server:
-  host: 0.0.0.0
-  port: 8080
+server:
+  host: 0.0.0.0
+  port: 8080
 
-logging:
-  level: INFO
-  console_output: true
+logging:
+  level: INFO
+  console_output: true
 
-extensions:
-  - type: routing
-    config:
-      regex_locations:
-        "__default__":
-          root: "./static"
-          index_file: "index.html"
+extensions: + - type: routing + config: + regex_locations: + "__default__": + root: "./static" + index_file: "index.html"

2. Create Static Directory

Create a static folder and add an index.html:

-
mkdir -p static
-echo '<h1>Hello from pyserve!</h1>' > static/index.html
+
mkdir -p static
+echo '<h1>Hello from pyserve!</h1>' > static/index.html

3. Start the Server

-
pyserve
+
pyserve

You should see output like:

-
Starting PyServe server on 0.0.0.0:8080
+
Starting PyServe server on 0.0.0.0:8080

4. Open in Browser

Navigate to http://localhost:8080 — you should see your page!

@@ -66,44 +66,44 @@ echo '<h1>Hello from pyserve!</h1>' > static/index.html

Using CLI Options

Override configuration via command line:

-
# Use a different config file
+        
# Use a different config file
 pyserve -c /path/to/config.yaml
 
-# Override host and port
+# Override host and port
 pyserve --host 127.0.0.1 --port 9000
 
-# Enable debug mode (verbose logging)
-pyserve --debug
+# Enable debug mode (verbose logging) +pyserve --debug

Example: Serve Documentation

Serve a documentation directory with proper caching:

-
http:
-  static_dir: ./docs
+        
http:
+  static_dir: ./docs
 
-server:
-  host: 0.0.0.0
-  port: 8000
+server:
+  host: 0.0.0.0
+  port: 8000
 
-extensions:
-  - type: routing
-    config:
-      regex_locations:
-        "=/":
-          root: "./docs"
-          index_file: "index.html"
+extensions:
+  - type: routing
+    config:
+      regex_locations:
+        "=/":
+          root: "./docs"
+          index_file: "index.html"
         
-        "~*\\.(css|js)$":
-          root: "./docs"
-          cache_control: "public, max-age=3600"
+        "~*\\.(css|js)$":
+          root: "./docs"
+          cache_control: "public, max-age=3600"
         
-        "~*\\.html$":
-          root: "./docs"
-          cache_control: "no-cache"
+        "~*\\.html$":
+          root: "./docs"
+          cache_control: "no-cache"
         
-        "__default__":
-          root: "./docs"
-          index_file: "index.html"
+ "__default__": + root: "./docs" + index_file: "index.html"
Next Steps: diff --git a/guides/asgi-mount.html b/guides/asgi-mount.html index da3df53..8ad7da8 100644 --- a/guides/asgi-mount.html +++ b/guides/asgi-mount.html @@ -45,15 +45,15 @@

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
+
extensions:
+  - type: asgi
+    config:
+      mounts:
+        - path: "/api"
+          app_path: "myapp.api:app"
+          app_type: asgi
+          name: "api-app"
+          strip_path: true

Mount Configuration Options

@@ -85,23 +85,23 @@

Mounting FastAPI

FastAPI applications are native ASGI:

-
# myapp/api.py
+        
# myapp/api.py
 from fastapi import FastAPI
 
 app = FastAPI()
 
 @app.get("/users")
 async def get_users():
-    return [{"id": 1, "name": "Alice"}]
+ return [{"id": 1, "name": "Alice"}]
-
extensions:
-  - type: asgi
-    config:
-      mounts:
-        - path: "/api"
-          app_path: "myapp.api:app"
-          app_type: asgi
-          name: "fastapi-app"
+
extensions:
+  - type: asgi
+    config:
+      mounts:
+        - path: "/api"
+          app_path: "myapp.api:app"
+          app_type: asgi
+          name: "fastapi-app"

With this configuration:

    @@ -112,23 +112,23 @@ async def get_users():

    Mounting Flask

    Flask applications are WSGI and will be automatically wrapped:

    -
    # myapp/flask_api.py
    +        
    # myapp/flask_api.py
     from flask import Flask
     
     app = Flask(__name__)
     
     @app.route("/hello")
     def hello():
    -    return {"message": "Hello from Flask!"}
    + return {"message": "Hello from Flask!"}
    -
    extensions:
    -  - type: asgi
    -    config:
    -      mounts:
    -        - path: "/flask"
    -          app_path: "myapp.flask_api:app"
    -          app_type: wsgi
    -          name: "flask-app"
    +
    extensions:
    +  - type: asgi
    +    config:
    +      mounts:
    +        - path: "/flask"
    +          app_path: "myapp.flask_api:app"
    +          app_type: wsgi
    +          name: "flask-app"
    Note: WSGI wrapping requires either a2wsgi or asgiref @@ -138,19 +138,19 @@ def hello():

    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"
    +
    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
    +        
    # myapp/api.py
     from fastapi import FastAPI
     
     def create_app(debug: bool = False, prefix: str = "/v1") -> FastAPI:
    @@ -160,19 +160,19 @@ def create_app(debug: bool = False, prefix: str = "/v1") -> FastAPI:
         async def status():
             return {"debug": debug}
         
    -    return app
    + 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"
    +
    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:

    @@ -198,31 +198,31 @@ def create_app(debug: bool = False, prefix: str = "/v1") -> FastAPI:

    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
    +        
    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
    +        # 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
    +        # 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"
    + # 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 @@ -236,24 +236,24 @@ def create_app(debug: bool = False, prefix: str = "/v1") -> FastAPI:

    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
    +        
    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"
    + # 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.

    diff --git a/guides/configuration.html b/guides/configuration.html index c57bcc6..8e1b54b 100644 --- a/guides/configuration.html +++ b/guides/configuration.html @@ -131,42 +131,42 @@

    List of extension modules to load. See Extensions Reference.

    Complete Example

    -
    http:
    -  static_dir: ./static
    -  templates_dir: ./templates
    +        
    http:
    +  static_dir: ./static
    +  templates_dir: ./templates
     
    -server:
    -  host: 0.0.0.0
    -  port: 8080
    -  backlog: 5
    -  default_root: false
    -  proxy_timeout: 30.0
    +server:
    +  host: 0.0.0.0
    +  port: 8080
    +  backlog: 5
    +  default_root: false
    +  proxy_timeout: 30.0
     
    -ssl:
    -  enabled: false
    -  cert_file: ./ssl/cert.pem
    -  key_file: ./ssl/key.pem
    +ssl:
    +  enabled: false
    +  cert_file: ./ssl/cert.pem
    +  key_file: ./ssl/key.pem
     
    -logging:
    -  level: INFO
    -  console_output: true
    -  format:
    -    type: standard
    -    use_colors: true
    -    timestamp_format: "%Y-%m-%d %H:%M:%S"
    -  files:
    -    - path: ./logs/pyserve.log
    -      level: DEBUG
    -      max_bytes: 10485760
    -      backup_count: 5
    +logging:
    +  level: INFO
    +  console_output: true
    +  format:
    +    type: standard
    +    use_colors: true
    +    timestamp_format: "%Y-%m-%d %H:%M:%S"
    +  files:
    +    - path: ./logs/pyserve.log
    +      level: DEBUG
    +      max_bytes: 10485760
    +      backup_count: 5
     
    -extensions:
    -  - type: routing
    -    config:
    -      regex_locations:
    -        "__default__":
    -          root: "./static"
    -          index_file: "index.html"
    +extensions: + - type: routing + config: + regex_locations: + "__default__": + root: "./static" + index_file: "index.html"
    Warning: When running in production, always use SSL diff --git a/guides/process-orchestration.html b/guides/process-orchestration.html index fb775e3..26147b3 100644 --- a/guides/process-orchestration.html +++ b/guides/process-orchestration.html @@ -41,7 +41,7 @@

Architecture

-
+        

                     PyServe Gateway (:8000)
                            │
           ┌────────────────┼────────────────┐
@@ -49,25 +49,25 @@
       FastAPI          Flask           Starlette
        :9001           :9002             :9003
       /api/*          /admin/*           /ws/*
-        
+

PyServe acts as a gateway, routing requests to the appropriate subprocess based on URL path.

Basic Configuration

-
server:
-  host: 0.0.0.0
-  port: 8000
+        
server:
+  host: 0.0.0.0
+  port: 8000
 
-extensions:
-  - type: process_orchestration
-    config:
-      apps:
-        - name: api
-          path: /api
-          app_path: myapp.api:app
+extensions:
+  - type: process_orchestration
+    config:
+      apps:
+        - name: api
+          path: /api
+          app_path: myapp.api:app
           
-        - name: admin
-          path: /admin
-          app_path: myapp.admin:app
+ - name: admin + path: /admin + app_path: myapp.admin:app

App Configuration Options

@@ -130,18 +130,18 @@

Global Configuration

-
extensions:
-  - type: process_orchestration
-    config:
-      port_range: [9000, 9999]
-      health_check_enabled: true
-      proxy_timeout: 60.0
-      logging:
-        httpx_level: warning
-        proxy_logs: true
-        health_check_logs: false
-      apps:
-        # ...
+
extensions:
+  - type: process_orchestration
+    config:
+      port_range: [9000, 9999]
+      health_check_enabled: true
+      proxy_timeout: 60.0
+      logging:
+        httpx_level: warning
+        proxy_logs: true
+        health_check_logs: false
+      apps:
+        # ...
port_range
@@ -161,7 +161,7 @@

FastAPI Example

-
# myapp/api.py
+        
# myapp/api.py
 from fastapi import FastAPI
 
 app = FastAPI()
@@ -172,22 +172,22 @@ async def health():
 
 @app.get("/users")
 async def get_users():
-    return [{"id": 1, "name": "Alice"}]
+ return [{"id": 1, "name": "Alice"}]
-
extensions:
-  - type: process_orchestration
-    config:
-      apps:
-        - name: api
-          path: /api
-          app_path: myapp.api:app
-          workers: 4
-          health_check_path: /health
+
extensions:
+  - type: process_orchestration
+    config:
+      apps:
+        - name: api
+          path: /api
+          app_path: myapp.api:app
+          workers: 4
+          health_check_path: /health

Requests to /api/users are proxied to the FastAPI process as /users.

Flask Example (WSGI)

-
# myapp/admin.py
+        
# myapp/admin.py
 from flask import Flask
 
 app = Flask(__name__)
@@ -198,17 +198,17 @@ def health():
 
 @app.route("/dashboard")
 def dashboard():
-    return {"page": "dashboard"}
+ return {"page": "dashboard"}
-
extensions:
-  - type: process_orchestration
-    config:
-      apps:
-        - name: admin
-          path: /admin
-          app_path: myapp.admin:app
-          app_type: wsgi
-          workers: 2
+
extensions:
+  - type: process_orchestration
+    config:
+      apps:
+        - name: admin
+          path: /admin
+          app_path: myapp.admin:app
+          app_type: wsgi
+          workers: 2
Note: WSGI support requires a2wsgi package: @@ -216,7 +216,7 @@ def dashboard():

Factory Pattern

-
# myapp/api.py
+        
# myapp/api.py
 from fastapi import FastAPI
 
 def create_app(debug: bool = False) -> FastAPI:
@@ -226,49 +226,49 @@ def create_app(debug: bool = False) -> FastAPI:
     async def health():
         return {"status": "ok", "debug": debug}
     
-    return app
+ return app
-
apps:
-  - name: api
-    path: /api
-    app_path: myapp.api:create_app
-    factory: true
+
apps:
+  - name: api
+    path: /api
+    app_path: myapp.api:create_app
+    factory: true

Environment Variables

Pass environment variables to subprocesses:

-
apps:
-  - name: api
-    path: /api
-    app_path: myapp.api:app
-    env:
-      DATABASE_URL: "postgresql://localhost/mydb"
-      REDIS_URL: "redis://localhost:6379"
-      DEBUG: "false"
+
apps:
+  - name: api
+    path: /api
+    app_path: myapp.api:app
+    env:
+      DATABASE_URL: "postgresql://localhost/mydb"
+      REDIS_URL: "redis://localhost:6379"
+      DEBUG: "false"

Multiple Applications

-
extensions:
-  - type: process_orchestration
-    config:
-      port_range: [9000, 9999]
-      apps:
-        # FastAPI REST API
-        - name: api
-          path: /api
-          app_path: apps.api:app
-          workers: 4
+        
extensions:
+  - type: process_orchestration
+    config:
+      port_range: [9000, 9999]
+      apps:
+        # FastAPI REST API
+        - name: api
+          path: /api
+          app_path: apps.api:app
+          workers: 4
         
-        # Flask Admin Panel
-        - name: admin
-          path: /admin
-          app_path: apps.admin:app
-          app_type: wsgi
-          workers: 2
+        # Flask Admin Panel
+        - name: admin
+          path: /admin
+          app_path: apps.admin:app
+          app_type: wsgi
+          workers: 2
         
-        # Starlette WebSocket Handler
-        - name: websocket
-          path: /ws
-          app_path: apps.websocket:app
-          workers: 1
+ # Starlette WebSocket Handler + - name: websocket + path: /ws + app_path: apps.websocket:app + workers: 1

Request Tracing

PyServe automatically generates and propagates X-Request-ID headers:

diff --git a/guides/reverse-proxy.html b/guides/reverse-proxy.html index acd152f..412d4a6 100644 --- a/guides/reverse-proxy.html +++ b/guides/reverse-proxy.html @@ -28,12 +28,12 @@

Basic Proxy Configuration

Use the proxy_pass directive in routing:

-
extensions:
-  - type: routing
-    config:
-      regex_locations:
-        "~^/api/":
-          proxy_pass: "http://localhost:9001"
+
extensions:
+  - type: routing
+    config:
+      regex_locations:
+        "~^/api/":
+          proxy_pass: "http://localhost:9001"

All requests to /api/* will be forwarded to http://localhost:9001/api/*.

@@ -62,21 +62,21 @@

Custom Headers

Add custom headers to proxied requests:

-
"~^/api/":
-  proxy_pass: "http://localhost:9001"
-  headers:
-    - "X-Custom-Header: my-value"
-    - "Authorization: Bearer token123"
+
"~^/api/":
+  proxy_pass: "http://localhost:9001"
+  headers:
+    - "X-Custom-Header: my-value"
+    - "Authorization: Bearer token123"

Dynamic Headers with Captures

Use regex capture groups to build dynamic headers:

-
"~^/api/v(?P<version>\\d+)/(?P<service>\\w+)":
-  proxy_pass: "http://localhost:9001"
-  headers:
-    - "X-API-Version: {version}"
-    - "X-Service: {service}"
-    - "X-Client-IP: $remote_addr"
+
"~^/api/v(?P<version>\\d+)/(?P<service>\\w+)":
+  proxy_pass: "http://localhost:9001"
+  headers:
+    - "X-API-Version: {version}"
+    - "X-Service: {service}"
+    - "X-Client-IP: $remote_addr"

Special variables:

    @@ -87,49 +87,49 @@

    Proxy Timeout

    Configure timeout for proxy requests:

    -
    # Global default timeout
    -server:
    -  proxy_timeout: 30.0
    +        
    # Global default timeout
    +server:
    +  proxy_timeout: 30.0
     
    -# Per-route timeout
    -extensions:
    -  - type: routing
    -    config:
    -      regex_locations:
    -        "~^/api/slow":
    -          proxy_pass: "http://localhost:9001"
    -          timeout: 120  # 2 minutes for slow endpoints
    +# Per-route timeout +extensions: + - type: routing + config: + regex_locations: + "~^/api/slow": + proxy_pass: "http://localhost:9001" + timeout: 120 # 2 minutes for slow endpoints

    URL Rewriting

    The proxy preserves the original request path by default:

    -
    # Request: GET /api/users/123
    -# Proxied: GET http://backend:9001/api/users/123
    -"~^/api/":
    -  proxy_pass: "http://backend:9001"
    +
    # Request: GET /api/users/123
    +# Proxied: GET http://backend:9001/api/users/123
    +"~^/api/":
    +  proxy_pass: "http://backend:9001"

    To proxy to a specific path:

    -
    # Request: GET /api/users/123
    -# Proxied: GET http://backend:9001/v2/users/123 (path preserved)
    -"~^/api/":
    -  proxy_pass: "http://backend:9001/v2"
    +
    # Request: GET /api/users/123
    +# Proxied: GET http://backend:9001/v2/users/123 (path preserved)
    +"~^/api/":
    +  proxy_pass: "http://backend:9001/v2"

    Load Balancing Example

    Route different services to different backends:

    -
    extensions:
    -  - type: routing
    -    config:
    -      regex_locations:
    -        "~^/api/users":
    -          proxy_pass: "http://user-service:8001"
    +        
    extensions:
    +  - type: routing
    +    config:
    +      regex_locations:
    +        "~^/api/users":
    +          proxy_pass: "http://user-service:8001"
             
    -        "~^/api/orders":
    -          proxy_pass: "http://order-service:8002"
    +        "~^/api/orders":
    +          proxy_pass: "http://order-service:8002"
             
    -        "~^/api/products":
    -          proxy_pass: "http://product-service:8003"
    + "~^/api/products": + proxy_pass: "http://product-service:8003"

    Error Handling

    pyserve returns appropriate error codes for proxy failures:

    diff --git a/guides/routing.html b/guides/routing.html index 233059e..8294381 100644 --- a/guides/routing.html +++ b/guides/routing.html @@ -62,29 +62,29 @@

    Routing Configuration

    Routing is configured via the routing extension:

    -
    extensions:
    -  - type: routing
    -    config:
    -      regex_locations:
    -        # Exact match for health check
    -        "=/health":
    -          return: "200 OK"
    -          content_type: "text/plain"
    +        
    extensions:
    +  - type: routing
    +    config:
    +      regex_locations:
    +        # Exact match for health check
    +        "=/health":
    +          return: "200 OK"
    +          content_type: "text/plain"
             
    -        # Static files with caching
    -        "~*\\.(js|css|png|jpg|gif|ico)$":
    -          root: "./static"
    -          cache_control: "public, max-age=31536000"
    +        # Static files with caching
    +        "~*\\.(js|css|png|jpg|gif|ico)$":
    +          root: "./static"
    +          cache_control: "public, max-age=31536000"
             
    -        # HTML files without caching
    -        "~*\\.html$":
    -          root: "./static"
    -          cache_control: "no-cache"
    +        # HTML files without caching
    +        "~*\\.html$":
    +          root: "./static"
    +          cache_control: "no-cache"
             
    -        # Default fallback
    -        "__default__":
    -          root: "./static"
    -          index_file: "index.html"
    + # Default fallback + "__default__": + root: "./static" + index_file: "index.html"

    Location Directives

    @@ -120,11 +120,11 @@

    Named Capture Groups

    Regex locations support named capture groups that can be used in headers and proxy URLs:

    -
    "~^/api/v(?P<version>\\d+)/(?P<resource>\\w+)":
    -  proxy_pass: "http://backend:9001"
    -  headers:
    -    - "X-API-Version: {version}"
    -    - "X-Resource: {resource}"
    +
    "~^/api/v(?P<version>\\d+)/(?P<resource>\\w+)":
    +  proxy_pass: "http://backend:9001"
    +  headers:
    +    - "X-API-Version: {version}"
    +    - "X-Resource: {resource}"

    Request to /api/v2/users will have headers:

      @@ -135,14 +135,14 @@

      SPA Configuration

      For Single Page Applications, use spa_fallback with exclude_patterns:

      -
      "__default__":
      -  spa_fallback: true
      -  root: "./dist"
      -  index_file: "index.html"
      -  exclude_patterns:
      -    - "/api/"
      -    - "/assets/"
      -    - "/static/"
      +
      "__default__":
      +  spa_fallback: true
      +  root: "./dist"
      +  index_file: "index.html"
      +  exclude_patterns:
      +    - "/api/"
      +    - "/assets/"
      +    - "/static/"

      This will:

        @@ -153,11 +153,11 @@

        Static File Serving

        Basic static file configuration:

        -
        "~*\\.(css|js|png|jpg|gif|svg|woff2?)$":
        -  root: "./static"
        -  cache_control: "public, max-age=86400"
        -  headers:
        -    - "X-Content-Type-Options: nosniff"
        +
        "~*\\.(css|js|png|jpg|gif|svg|woff2?)$":
        +  root: "./static"
        +  cache_control: "public, max-age=86400"
        +  headers:
        +    - "X-Content-Type-Options: nosniff"
        Note: pyserve automatically detects MIME types based on file extensions. diff --git a/reference/asgi-mount.html b/reference/asgi-mount.html index 46c61b3..60971f3 100644 --- a/reference/asgi-mount.html +++ b/reference/asgi-mount.html @@ -31,18 +31,18 @@

        ASGIAppLoader

        Loads and manages ASGI/WSGI applications from Python import paths.

        -
        from pyserve import ASGIAppLoader
        +        
        from pyserve import ASGIAppLoader
         
         loader = ASGIAppLoader()
         
        -# Load an ASGI app
        +# 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
        -)
        + app_path="mymodule:app", + app_type="asgi", + module_path="/path/to/project", + factory=False, + factory_args=None +)
        Methods
        @@ -69,14 +69,14 @@ app = loader.load_app(

        MountedApp

        Represents an application mounted at a specific path.

        -
        from pyserve import MountedApp
        +        
        from pyserve import MountedApp
         
         mount = MountedApp(
        -    path="/api",
        +    path="/api",
             app=my_asgi_app,
        -    name="my-api",
        -    strip_path=True
        -)
        + name="my-api", + strip_path=True +)
        Attributes
        @@ -105,19 +105,19 @@ mount = MountedApp(

        ASGIMountManager

        Manages multiple mounted applications and routes requests.

        -
        from pyserve import ASGIMountManager
        +        
        from pyserve import ASGIMountManager
         
         manager = ASGIMountManager()
         
        -# Mount using app instance
        -manager.mount(path="/api", app=my_app)
        +# Mount using app instance
        +manager.mount(path="/api", app=my_app)
         
        -# Mount using import path
        +# Mount using import path
         manager.mount(
        -    path="/flask",
        -    app_path="myapp:flask_app",
        -    app_type="wsgi"
        -)
        + path="/flask", + app_path="myapp:flask_app", + app_type="wsgi" +)
        Methods
        @@ -150,80 +150,80 @@ manager.mount(

        Convenience functions for loading specific framework applications:

        create_fastapi_app()

        -
        from pyserve import create_fastapi_app
        +        
        from pyserve import create_fastapi_app
         
         app = create_fastapi_app(
        -    app_path="myapp.api:app",
        -    module_path=None,
        -    factory=False,
        -    factory_args=None
        -)
        + app_path="myapp.api:app", + module_path=None, + factory=False, + factory_args=None +)

        create_flask_app()

        -
        from pyserve import create_flask_app
        +        
        from pyserve import create_flask_app
         
         app = create_flask_app(
        -    app_path="myapp.web:app",
        -    module_path=None,
        -    factory=False,
        -    factory_args=None
        -)
        + app_path="myapp.web:app", + module_path=None, + factory=False, + factory_args=None +)

        Automatically wraps the WSGI app for ASGI compatibility.

        create_django_app()

        -
        from pyserve import create_django_app
        +        
        from pyserve import create_django_app
         
         app = create_django_app(
        -    settings_module="myproject.settings",
        -    module_path="/path/to/project"
        -)
        + settings_module="myproject.settings", + module_path="/path/to/project" +)

        Sets DJANGO_SETTINGS_MODULE and returns Django's ASGI application.

        create_starlette_app()

        -
        from pyserve import create_starlette_app
        +        
        from pyserve import create_starlette_app
         
         app = create_starlette_app(
        -    app_path="myapp:starlette_app",
        -    module_path=None,
        -    factory=False,
        -    factory_args=None
        -)
        + app_path="myapp:starlette_app", + module_path=None, + factory=False, + factory_args=None +)

        Usage Example

        Complete example mounting multiple applications:

        -
        from pyserve import (
        +        
        from pyserve import (
             PyServeServer,
             ASGIMountManager,
             create_fastapi_app,
             create_flask_app
         )
         
        -# Create mount manager
        +# 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 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")
        +# 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']}")
        +# List mounts +for mount in mounts.list_mounts(): + print(f"Mounted {mount['name']} at {mount['path']}")

        Error Handling

        All loader functions return None on failure and log errors. Check the return value before using:

        -
        app = create_fastapi_app("nonexistent:app")
        -if app is None:
        -    # Handle error - check logs for details
        -    print("Failed to load application")
        +
        app = create_fastapi_app("nonexistent:app")
        +if app is None:
        +    # Handle error - check logs for details
        +    print("Failed to load application")

        WSGI Compatibility

        For WSGI applications, pyserve uses adapters in this priority:

        @@ -233,9 +233,9 @@ admin_app = create_flask_app("myapp.admin:app")

        Install an adapter:

        -
        pip install a2wsgi  # recommended
        -# or
        -pip install asgiref
        +
        pip install a2wsgi  # recommended
        +# or
        +pip install asgiref
        See Also: diff --git a/reference/cli.html b/reference/cli.html index 5015a58..a26d6c9 100644 --- a/reference/cli.html +++ b/reference/cli.html @@ -26,7 +26,7 @@

        pyserve provides a command-line interface for server management.

        Synopsis

        -
        pyserve [OPTIONS]
        +
        pyserve [OPTIONS]

        Options

        @@ -66,20 +66,20 @@

        Examples

        Start with default configuration:

        -
        pyserve
        +
        pyserve

        Start with custom config file:

        -
        pyserve -c /path/to/config.yaml
        +
        pyserve -c /path/to/config.yaml

        Override host and port:

        -
        pyserve --host 127.0.0.1 --port 9000
        +
        pyserve --host 127.0.0.1 --port 9000

        Enable debug mode:

        -
        pyserve --debug
        +
        pyserve --debug

        Show version:

        -
        pyserve --version
        -# Output: pyserve 0.7.0
        +
        pyserve --version
        +# Output: pyserve 0.7.0

        Configuration Priority

        Settings are applied in the following order (later overrides earlier):

        @@ -125,15 +125,15 @@

        Development Commands (Makefile)

        When working with the source repository, use make commands:

        -
        make run           # Start in development mode
        -make run-prod      # Start in production mode
        -make test          # Run tests
        -make test-cov      # Tests with coverage
        -make lint          # Check code with linters
        -make format        # Format code
        -make build         # Build wheel package
        -make clean         # Clean temporary files
        -make help          # Show all commands
        +
        make run           # Start in development mode
        +make run-prod      # Start in production mode
        +make test          # Run tests
        +make test-cov      # Tests with coverage
        +make lint          # Check code with linters
        +make format        # Format code
        +make build         # Build wheel package
        +make clean         # Clean temporary files
        +make help          # Show all commands
        -
        - type: security
        -  config:
        -    security_headers:
        -      X-Frame-Options: DENY
        -      X-Content-Type-Options: nosniff
        -      X-XSS-Protection: "1; mode=block"
        -      Strict-Transport-Security: "max-age=31536000"
        -    blocked_ips:
        -      - "192.168.1.100"
        -      - "10.0.0.50"
        +
        - type: security
        +  config:
        +    security_headers:
        +      X-Frame-Options: DENY
        +      X-Content-Type-Options: nosniff
        +      X-XSS-Protection: "1; mode=block"
        +      Strict-Transport-Security: "max-age=31536000"
        +    blocked_ips:
        +      - "192.168.1.100"
        +      - "10.0.0.50"

        Default security headers if not specified:

          @@ -125,11 +125,11 @@
          Default cache TTL in seconds. Default: 3600
        -
        - type: caching
        -  config:
        -    cache_ttl: 3600
        -    cache_patterns:
        -      - "/api/public/*"
        +
        - type: caching
        +  config:
        +    cache_ttl: 3600
        +    cache_patterns:
        +      - "/api/public/*"

        Monitoring Extension

        Collects request metrics and provides statistics.

        @@ -140,9 +140,9 @@
        Enable metrics collection. Default: true
        -
        - type: monitoring
        -  config:
        -    enable_metrics: true
        +
        - type: monitoring
        +  config:
        +    enable_metrics: true

        Collected metrics (available at /metrics):

          @@ -220,28 +220,28 @@
          Django settings module (for Django apps only)
-
- type: asgi
-  config:
-    mounts:
-      # FastAPI application
-      - path: "/api"
-        app_path: "myapp.api:app"
-        app_type: asgi
-        name: "api"
+        
- type: asgi
+  config:
+    mounts:
+      # FastAPI application
+      - path: "/api"
+        app_path: "myapp.api:app"
+        app_type: asgi
+        name: "api"
       
-      # Flask application (WSGI)
-      - path: "/admin"
-        app_path: "myapp.admin:app"
-        app_type: wsgi
-        name: "admin"
+      # Flask application (WSGI)
+      - path: "/admin"
+        app_path: "myapp.admin:app"
+        app_type: wsgi
+        name: "admin"
       
-      # Factory pattern with arguments
-      - path: "/api/v2"
-        app_path: "myapp.api:create_app"
-        factory: true
-        factory_args:
-          debug: true
-          version: "2.0"
+ # Factory pattern with arguments + - path: "/api/v2" + app_path: "myapp.api:create_app" + factory: true + factory_args: + debug: true + version: "2.0"

Supported frameworks:

-
- type: process_orchestration
-  config:
-    port_range: [9000, 9999]
-    health_check_enabled: true
-    proxy_timeout: 60.0
-    logging:
-      httpx_level: warning
-      proxy_logs: true
-      health_check_logs: false
-    apps:
-      - name: api
-        path: /api
-        app_path: myapp.api:app
-        workers: 4
-        health_check_path: /health
+        
- type: process_orchestration
+  config:
+    port_range: [9000, 9999]
+    health_check_enabled: true
+    proxy_timeout: 60.0
+    logging:
+      httpx_level: warning
+      proxy_logs: true
+      health_check_logs: false
+    apps:
+      - name: api
+        path: /api
+        app_path: myapp.api:app
+        workers: 4
+        health_check_path: /health
       
-      - name: admin
-        path: /admin
-        app_path: myapp.admin:app
-        app_type: wsgi
-        workers: 2
+ - name: admin + path: /admin + app_path: myapp.admin:app + app_type: wsgi + workers: 2

App Configuration

diff --git a/style.css b/style.css index 34427e2..869d726 100644 --- a/style.css +++ b/style.css @@ -221,21 +221,6 @@ dd { text-align: center; } -/* Syntax highlighting for config examples */ -.directive { - color: #5fba7d; - font-weight: bold; -} - -.value { - color: #87ceeb; -} - -.comment { - color: #666; - font-style: italic; -} - /* Main wrapper for two-column layout */ #main-wrapper { display: flex;