docs: update documentation for /platforms/ URL routing strategy

- Add multi-platform URL routing section to url-routing/overview.md
- Update multi-platform-cms.md with new request flow diagrams
- Add PlatformContextMiddleware documentation to middleware.md
- Update middleware execution order diagram
- Add Phase 7 (Platform URL Routing Strategy) to implementation plan
- Update platform URL summary tables across all docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-19 18:32:03 +01:00
parent a2407ae418
commit 4f55fe31c8
4 changed files with 297 additions and 32 deletions

View File

@@ -14,7 +14,61 @@ This middleware layer is **system-wide** and enables the multi-tenant architectu
## Middleware Components
### 1. Logging Middleware
### 1. Platform Context Middleware
**Purpose**: Detect which platform (OMS, Loyalty, Main) the request is for
**What it does**:
- Detects platform from:
- Custom domain (e.g., `oms.lu`, `loyalty.lu`)
- Path prefix in development (e.g., `/platforms/oms/`, `/platforms/loyalty/`)
- Default to `main` platform for localhost without prefix
- Rewrites path for platform-prefixed requests (strips `/platforms/{code}/`)
- Queries database to find platform by domain or code
- Injects platform object into `request.state.platform`
**URL Detection Logic**:
```
Request arrives
┌─────────────────────────────────────┐
│ Production domain? (oms.lu, etc.) │
└─────────────────────────────────────┘
│ YES → Use that platform
▼ NO (localhost)
┌─────────────────────────────────────┐
│ Path starts with /platforms/{code}? │
└─────────────────────────────────────┘
│ YES → Strip prefix, use platform
│ /platforms/oms/pricing → /pricing
▼ NO
┌─────────────────────────────────────┐
│ Use 'main' platform (DEFAULT) │
│ Path unchanged │
└─────────────────────────────────────┘
```
**Example**:
```
Request: https://localhost:9999/platforms/oms/pricing
Middleware detects: platform_code = "oms"
Rewrites path: /platforms/oms/pricing → /pricing
Queries database: SELECT * FROM platforms WHERE code = 'oms'
Injects: request.state.platform = <Platform object>
```
**Why it's critical**: Without this, the system wouldn't know which platform's content to serve
**Configuration**: Runs BEFORE VendorContextMiddleware (sets platform context first)
### 2. Logging Middleware
**Purpose**: Request/response logging and performance monitoring
@@ -221,13 +275,14 @@ from middleware import context_middleware
```mermaid
graph TD
A[Client Request] --> B[1. LoggingMiddleware]
B --> C[2. VendorContextMiddleware]
C --> D[3. ContextDetectionMiddleware]
D --> E[4. ThemeContextMiddleware]
E --> F[5. FastAPI Router]
F --> G[Route Handler]
G --> H[Response]
H --> I[Client]
B --> C[2. PlatformContextMiddleware]
C --> D[3. VendorContextMiddleware]
D --> E[4. ContextDetectionMiddleware]
E --> F[5. ThemeContextMiddleware]
F --> G[6. FastAPI Router]
G --> H[Route Handler]
H --> I[Response]
I --> J[Client]
```
### Why This Order Matters
@@ -238,21 +293,27 @@ graph TD
- Needs to wrap everything to measure total time
- Must log errors from all other middleware
2. **VendorContextMiddleware second**
2. **PlatformContextMiddleware second**
- Must run before VendorContextMiddleware (sets platform context)
- Rewrites path for `/platforms/{code}/` prefixed requests
- Sets `request.state.platform` for downstream middleware
3. **VendorContextMiddleware third**
- Uses rewritten path from PlatformContextMiddleware
- Must run before ContextDetectionMiddleware (provides vendor and clean_path)
- Must run before ThemeContextMiddleware (provides vendor_id)
3. **ContextDetectionMiddleware third**
4. **ContextDetectionMiddleware fourth**
- Uses clean_path from VendorContextMiddleware
- Provides context_type for ThemeContextMiddleware
4. **ThemeContextMiddleware last**
5. **ThemeContextMiddleware last**
- Depends on vendor from VendorContextMiddleware
- Depends on context_type from ContextDetectionMiddleware
**Breaking this order will break the application!**
**Note:** Path-based routing (e.g., `/vendors/{code}/shop/*`) is handled by double router mounting in `main.py`, not by middleware.
**Note:** Path-based routing (e.g., `/vendors/{code}/shop/*`) is handled by double router mounting in `main.py`, not by middleware. Platform path-based routing (e.g., `/platforms/oms/`) IS handled by PlatformContextMiddleware which rewrites the path.
## Request State Variables
@@ -260,6 +321,8 @@ Middleware components inject these variables into `request.state`:
| Variable | Set By | Type | Used By | Description |
|----------|--------|------|---------|-------------|
| `platform` | PlatformContextMiddleware | Platform | Routes, Content | Current platform object (main, oms, loyalty) |
| `platform_context` | PlatformContextMiddleware | dict | Routes | Platform detection details (method, paths) |
| `vendor` | VendorContextMiddleware | Vendor | Theme, Templates | Current vendor object |
| `vendor_id` | VendorContextMiddleware | int | Queries, Theme | Current vendor ID |
| `clean_path` | VendorContextMiddleware | str | Context | Path without vendor prefix (for context detection) |