docs: update routing docs and seed script for production routing changes
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

Reflect the production routing refactor (ce5b54f): document store dashboard
double-mounting, per-platform subdomain overrides via StorePlatform.custom_subdomain,
get_resolved_store_code dependency, and /merchants/ reserved path. Update seed
script to populate custom_subdomain and StoreDomain.platform_id for demo data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 11:44:43 +01:00
parent ce5b54f27b
commit d480b59df4
5 changed files with 238 additions and 51 deletions

View File

@@ -82,27 +82,33 @@ logger.info(f"Request: GET /storefront/products from 192.168.1.100")
- Queries database for store
- Extracts clean path
**Example Processing** (Subdomain Mode):
**Example Processing** (Subdomain Mode — Two-Step Lookup):
```python
# Input
host = "orion.platform.com"
host = "wizatech-rewards.rewardflow.lu"
path = "/storefront/products"
# Detection logic
if host != settings.platform_domain:
# Subdomain detected
store_code = host.split('.')[0] # "orion"
# Detection logic — two-step subdomain lookup
subdomain = host.split('.')[0] # "wizatech-rewards"
# Query database
# Step 1: Check per-platform custom subdomain (StorePlatform.custom_subdomain)
store_platform = db.query(StorePlatform).filter(
StorePlatform.custom_subdomain == subdomain
).first()
if store_platform:
store = store_platform.store
else:
# Step 2: Fall back to standard Store.subdomain
store = db.query(Store).filter(
Store.code == store_code
Store.subdomain == subdomain
).first()
# Set request state
request.state.store = store
request.state.store_id = store.id
request.state.clean_path = "/storefront/products" # Already clean
# Set request state
request.state.store = store
request.state.store_id = store.id
request.state.clean_path = "/storefront/products" # Already clean
```
**Request State After**:
@@ -116,23 +122,32 @@ request.state.clean_path = "/storefront/products"
**What happens**:
- FastAPI matches the request path against registered routes
- For path-based development mode, routes are registered with two prefixes:
- `/storefront/*` for subdomain/custom domain
- `/stores/{store_code}/storefront/*` for path-based development
- Both storefront and store dashboard routes are registered with two prefixes each:
- Storefront: `/storefront/*` and `/storefront/{store_code}/*`
- Store dashboard: `/store/*` and `/store/{store_code}/*`
**Example** (Path-Based Mode):
```python
# In main.py - Double router mounting
# In main.py - Double router mounting for storefront
app.include_router(storefront_pages.router, prefix="/storefront")
app.include_router(storefront_pages.router, prefix="/stores/{store_code}/storefront")
app.include_router(storefront_pages.router, prefix="/storefront/{store_code}")
# Request: /stores/ORION/storefront/products
# Matches: Second router (/stores/{store_code}/storefront)
# Route: @router.get("/products")
# store_code available as path parameter = "ORION"
# In main.py - Double router mounting for store dashboard
app.include_router(store_pages.router, prefix="/store")
app.include_router(store_pages.router, prefix="/store/{store_code}")
# Storefront request: /storefront/ACME/products
# Matches: Second storefront router (/storefront/{store_code})
# store_code = "ACME"
# Store dashboard request: /store/ACME/dashboard
# Matches: Second store router (/store/{store_code})
# store_code = "ACME"
```
Route handlers use the `get_resolved_store_code` dependency to transparently resolve the store code from either the path parameter (dev mode) or middleware state (production subdomain/custom domain).
**Note:** Previous implementations used `PathRewriteMiddleware` to rewrite paths. This has been replaced with FastAPI's native routing via double router mounting.
**Request State After**: No changes to state, but internal path updated