Fixed url pattern in the doc for path-based shops

This commit is contained in:
2025-11-18 23:18:13 +01:00
parent b3009e3795
commit f14686c131
8 changed files with 68 additions and 52 deletions

View File

@@ -211,6 +211,14 @@ Set-Cookie: vendor_token=<JWT>; Path=/vendor; HttpOnly; Secure; SameSite=Lax
**Purpose:** Product browsing (public), customer accounts, orders, profile management.
**Important - URL Pattern Context:**
The `/shop/*` routes work differently depending on deployment mode:
- **Subdomain Mode** (Production): `https://vendor.platform.com/shop/products`
- **Custom Domain** (Production): `https://customdomain.com/shop/products`
- **Path-Based** (Development): `http://localhost:8000/vendors/{vendor_code}/shop/products`
In path-based development mode, the full URL includes the vendor code (e.g., `/vendors/acme/shop/products`), but the routes are still defined as `/shop/*` internally. See [URL Routing Guide](../architecture/url-routing/overview.md) for details.
**Access Control:**
- **Public Routes** (`/shop/products`, `/shop/cart`, etc.):
- ✅ Anyone can access (no authentication)

View File

@@ -73,9 +73,9 @@ Injects: request.state.vendor = <Vendor object>
- Rewrites `request.scope['path']` to remove vendor prefix
- Allows FastAPI routes to match correctly
**Example**:
**Example** (Path-Based Development Mode):
```
Original path: /vendor/WIZAMART/shop/products
Original path: /vendors/WIZAMART/shop/products
Clean path: /shop/products (set by VendorContextMiddleware)
Path Rewrite Middleware changes request path to: /shop/products

View File

@@ -8,6 +8,11 @@ The Wizamart platform supports **three deployment modes** for multi-tenancy, all
**Key Concept**: One application, multiple isolated vendor shops, each accessible via different URLs.
**Important Distinction:**
- **Vendor Dashboard** (all modes): `/vendor/{code}/*` (singular) - Management interface for vendors
- **Shop Storefront** (path-based only): `/vendors/{code}/shop/*` (plural) - Customer-facing shop
- This naming distinction helps separate administrative routes from public-facing shop routes
## The Three Routing Modes
### 1. Custom Domain Mode
@@ -75,9 +80,9 @@ id | code | name
**Example**:
```
platform.com/vendor/vendor1/shop → Vendor 1 Shop
platform.com/vendor/vendor2/shop → Vendor 2 Shop
platform.com/vendors/vendor3/shop → Vendor 3 Shop (alternative)
platform.com/vendors/vendor1/shop → Vendor 1 Shop
platform.com/vendors/vendor2/shop → Vendor 2 Shop
platform.com/vendors/vendor3/shop → Vendor 3 Shop
```
**How it works**:
@@ -86,12 +91,11 @@ platform.com/vendors/vendor3/shop → Vendor 3 Shop (alternative)
3. Path is rewritten for routing
4. All vendors on same domain
**Use Case**: Simplest deployment, single domain certificate
**Use Case**: Development and testing environments only
**Path Patterns**:
- `/vendor/{code}/shop/*` - Storefront pages
- `/vendor/{code}/api/*` - API endpoints (if needed)
- `/vendors/{code}/shop/*` - Alternative pattern
- `/vendors/{code}/shop/*` - Storefront pages (correct pattern)
- `/vendor/{code}/*` - Vendor dashboard pages (different context)
## Routing Mode Comparison
@@ -142,20 +146,22 @@ def detect_vendor(request):
For path-based routing, clean paths are extracted:
**Example 1**: Single vendor prefix
```
Original: /vendor/WIZAMART/shop/products
Extracted: vendor_code = "WIZAMART"
Clean: /shop/products
```
**Example 2**: Plural vendors prefix
**Path-Based Shop Routes** (Development):
```
Original: /vendors/WIZAMART/shop/products
Extracted: vendor_code = "WIZAMART"
Clean: /shop/products
```
**Vendor Dashboard Routes** (All environments):
```
Original: /vendor/WIZAMART/dashboard
Extracted: vendor_code = "WIZAMART"
Clean: /dashboard
```
**Note**: The shop storefront uses `/vendors/` (plural) while the vendor dashboard uses `/vendor/` (singular). This distinction helps separate customer-facing shop routes from vendor management routes.
**Why Clean Path?**
- FastAPI routes don't include vendor prefix
- Routes defined as: `@app.get("/shop/products")`
@@ -214,9 +220,9 @@ INSERT INTO vendor_domains (vendor_id, domain) VALUES
**URLs**:
```
myplatform.com/admin
myplatform.com/vendor/shop1/shop
myplatform.com/vendor/shop2/shop
myplatform.com/vendor/shop3/shop
myplatform.com/vendors/shop1/shop
myplatform.com/vendors/shop2/shop
myplatform.com/vendors/shop3/shop
```
**Infrastructure**:
@@ -266,8 +272,8 @@ shop3.myplatform.com → Vendor 3
shop4.myplatform.com → Vendor 4
# Path-based (free tier)
myplatform.com/vendor/shop5/shop → Vendor 5
myplatform.com/vendor/shop6/shop → Vendor 6
myplatform.com/vendors/shop5/shop → Vendor 5
myplatform.com/vendors/shop6/shop → Vendor 6
```
**Infrastructure**:
@@ -433,7 +439,7 @@ Host: wizamart.myplatform.com
**Request**:
```http
GET /vendor/WIZAMART/shop/products HTTP/1.1
GET /vendors/WIZAMART/shop/products HTTP/1.1
Host: myplatform.com
```

View File

@@ -47,11 +47,11 @@ vendor2.platform.com → Vendor 2 Shop
admin.platform.com → Admin Interface
```
#### Path-Based Mode
#### Path-Based Mode (Development Only)
```
platform.com/vendor/vendor1/shop → Vendor 1 Shop
platform.com/vendor/vendor2/shop → Vendor 2 Shop
platform.com/admin → Admin Interface
platform.com/vendors/vendor1/shop → Vendor 1 Shop
platform.com/vendors/vendor2/shop → Vendor 2 Shop
platform.com/admin → Admin Interface
```
**See:** [Multi-Tenant System](multi-tenant.md) for detailed implementation

View File

@@ -121,8 +121,8 @@ request.state.clean_path = "/shop/products"
**Example** (Path-Based Mode):
```python
# Input (path-based mode)
original_path = "/vendor/WIZAMART/shop/products"
# Input (path-based development mode)
original_path = "/vendors/WIZAMART/shop/products"
clean_path = "/shop/products" # From VendorContextMiddleware
# Path rewrite

View File

@@ -6,6 +6,8 @@
There are three ways depending on the deployment mode:
**⚠️ Important:** This guide describes **customer-facing shop routes**. For vendor dashboard/management routes, see [Vendor Dashboard Documentation](../../vendor/). The shop uses `/vendors/{code}/shop/*` (plural) in path-based mode, while the vendor dashboard uses `/vendor/{code}/*` (singular).
### 1. **SUBDOMAIN MODE** (Production - Recommended)
```
https://VENDOR_SUBDOMAIN.platform.com/shop/products
@@ -26,11 +28,11 @@ https://shop.techpro.io/shop/cart
### 3. **PATH-BASED MODE** (Development Only)
```
http://localhost:PORT/vendor/VENDOR_CODE/shop/products
http://localhost:PORT/vendors/VENDOR_CODE/shop/products
Example:
http://localhost:8000/vendor/acme/shop/products
http://localhost:8000/vendor/techpro/shop/checkout
http://localhost:8000/vendors/acme/shop/products
http://localhost:8000/vendors/techpro/shop/checkout
```
---
@@ -107,15 +109,15 @@ id | vendor_id | domain | is_active | is_verified
### 3. PATH-BASED MODE (Development Only)
**URL Pattern:** `http://localhost:PORT/vendor/VENDOR_CODE/shop/...`
**URL Pattern:** `http://localhost:PORT/vendors/VENDOR_CODE/shop/...`
**Example:**
- Development: `http://localhost:8000/vendor/acme/shop/products`
- With port: `http://localhost:8000/vendor/acme/shop/products/123`
- Development: `http://localhost:8000/vendors/acme/shop/products`
- With port: `http://localhost:8000/vendors/acme/shop/products/123`
**How It Works:**
1. Developer visits `http://localhost:8000/vendor/acme/shop/products`
2. `vendor_context_middleware` detects path-based routing pattern `/vendor/acme/...`
1. Developer visits `http://localhost:8000/vendors/acme/shop/products`
2. `vendor_context_middleware` detects path-based routing pattern `/vendors/acme/...`
3. Extracts vendor code `"acme"` from the path
4. Looks up Vendor: `SELECT * FROM vendors WHERE subdomain = 'acme'`
5. Sets `request.state.vendor = Vendor(acme)`
@@ -151,12 +153,12 @@ https://acme.wizamart.com/shop/account/profile → Profile (Auth Require
### Path-Based (DEVELOPMENT)
```
http://localhost:8000/vendor/acme/shop/ → Homepage
http://localhost:8000/vendor/acme/shop/products → Products
http://localhost:8000/vendor/acme/shop/products/123 → Product Detail
http://localhost:8000/vendor/acme/shop/cart → Cart
http://localhost:8000/vendor/acme/shop/checkout → Checkout
http://localhost:8000/vendor/acme/shop/account/login → Login
http://localhost:8000/vendors/acme/shop/ → Homepage
http://localhost:8000/vendors/acme/shop/products → Products
http://localhost:8000/vendors/acme/shop/products/123 → Product Detail
http://localhost:8000/vendors/acme/shop/cart → Cart
http://localhost:8000/vendors/acme/shop/checkout → Checkout
http://localhost:8000/vendors/acme/shop/account/login → Login
```
### API Endpoints (Same for All Modes)
@@ -350,9 +352,9 @@ In Jinja2 template:
The `vendor_context_middleware` sets `clean_path` for path-based URLs, but this isn't used for FastAPI routing.
**Problem:**
- Incoming: `GET http://localhost:8000/vendor/acme/shop/products`
- Incoming: `GET http://localhost:8000/vendors/acme/shop/products`
- Routes registered: `@router.get("/shop/products")`
- FastAPI tries to match `/vendor/acme/shop/products` against `/shop/products`
- FastAPI tries to match `/vendors/acme/shop/products` against `/shop/products`
- Result: ❌ 404 Not Found
**Solution (Recommended):**
@@ -374,7 +376,7 @@ app.middleware("http")(path_rewrite_middleware)
Or alternatively, mount the router twice:
```python
app.include_router(shop_pages.router, prefix="/shop")
app.include_router(shop_pages.router, prefix="/vendor") # Allows /vendor/* paths
app.include_router(shop_pages.router, prefix="/vendors/{vendor_code}/shop") # Path-based development mode
```
---
@@ -401,7 +403,7 @@ Set-Cookie: customer_token=eyJ...; Path=/shop; HttpOnly; SameSite=Lax
|------|-----|----------|-----|-----|
| Subdomain | `vendor.platform.com/shop` | Production (standard) | *.platform.com | Add subdomains |
| Custom Domain | `vendor-domain.com/shop` | Production (premium) | Per vendor | Vendor configures |
| Path-Based | `localhost:8000/vendor/v/shop` | Development only | None | None |
| Path-Based | `localhost:8000/vendors/v/shop` | Development only | None | None |
---

View File

@@ -207,7 +207,7 @@ Middleware for request/response logging and performance monitoring.
Middleware function that rewrites request paths for path-based vendor routing.
**Purpose:**
Allows `/vendor/VENDORCODE/shop/products` to be internally routed as `/shop/products` for proper FastAPI route matching.
Allows `/vendors/VENDORCODE/shop/products` (path-based development mode) to be internally routed as `/shop/products` for proper FastAPI route matching.
**Execution Order:**
Must run AFTER VendorContextMiddleware and BEFORE ContextDetectionMiddleware.

View File

@@ -66,11 +66,11 @@ vendor2.platform.com → Vendor 2 Shop
admin.platform.com → Admin Interface
```
**3. Path-Based Mode**
**3. Path-Based Mode** (Development Only)
```
platform.com/vendor/vendor1/shop → Vendor 1 Shop
platform.com/vendor/vendor2/shop → Vendor 2 Shop
platform.com/admin → Admin Interface
platform.com/vendors/vendor1/shop → Vendor 1 Shop
platform.com/vendors/vendor2/shop → Vendor 2 Shop
platform.com/admin → Admin Interface
```
**Learn more**: [Multi-Tenant System](architecture/multi-tenant.md)