refactor: remove legacy /shop and /api/v1/shop dead code

After the storefront migration, no live routes mount under /api/v1/shop/.
Remove all dead code that detected/handled shop API requests: the
is_shop_api_request() method, the shop API dispatch branch in middleware,
the RequestContext.SHOP enum member (renamed to STOREFRONT), legacy path
prefixes in FrontendDetector, and all associated tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 13:16:43 +01:00
parent 874e254c11
commit 9173448645
10 changed files with 76 additions and 333 deletions

View File

@@ -14,7 +14,7 @@ Migration guide:
- RequestContext.API -> Check with FrontendDetector.is_api_request()
- RequestContext.ADMIN -> FrontendType.ADMIN
- RequestContext.STORE_DASHBOARD -> FrontendType.STORE
- RequestContext.SHOP -> FrontendType.STOREFRONT
- RequestContext.STOREFRONT -> FrontendType.STOREFRONT
- RequestContext.FALLBACK -> FrontendType.PLATFORM (or handle API separately)
- get_request_context(request) -> get_frontend_type(request)
@@ -44,14 +44,14 @@ class RequestContext(str, Enum):
- API -> Use FrontendDetector.is_api_request() + FrontendType
- ADMIN -> FrontendType.ADMIN
- STORE_DASHBOARD -> FrontendType.STORE
- SHOP -> FrontendType.STOREFRONT
- STOREFRONT -> FrontendType.STOREFRONT
- FALLBACK -> FrontendType.PLATFORM
"""
API = "api"
ADMIN = "admin"
STORE_DASHBOARD = "store"
SHOP = "shop"
STOREFRONT = "storefront"
FALLBACK = "fallback"
@@ -82,7 +82,7 @@ def get_request_context(request: Request) -> RequestContext:
mapping = {
FrontendType.ADMIN: RequestContext.ADMIN,
FrontendType.STORE: RequestContext.STORE_DASHBOARD,
FrontendType.STOREFRONT: RequestContext.SHOP,
FrontendType.STOREFRONT: RequestContext.STOREFRONT,
FrontendType.PLATFORM: RequestContext.FALLBACK,
}

View File

@@ -239,31 +239,26 @@ class StoreContextManager:
"""Check if request is for API endpoints."""
return FrontendDetector.is_api_request(request.url.path)
@staticmethod
def is_shop_api_request(request: Request) -> bool:
"""Check if request is for shop API endpoints."""
return request.url.path.startswith("/api/v1/shop/")
@staticmethod
def extract_store_from_referer(request: Request) -> dict | None:
"""
Extract store context from Referer header.
Used for shop API requests where store context comes from the page
that made the API call (e.g., JavaScript on /stores/wizamart/shop/products
calling /api/v1/shop/products).
Used for storefront API requests where store context comes from the page
that made the API call (e.g., JavaScript on /stores/wizamart/storefront/products
calling /api/v1/storefront/products).
Extracts store from Referer URL patterns:
- http://localhost:8000/stores/wizamart/shop/... → wizamart
- http://wizamart.platform.com/shop/... → wizamart (subdomain) # noqa
- http://custom-domain.com/shop/... → custom-domain.com # noqa
- http://localhost:8000/stores/wizamart/storefront/... → wizamart
- http://wizamart.platform.com/storefront/... → wizamart (subdomain) # noqa
- http://custom-domain.com/storefront/... → custom-domain.com # noqa
Returns store context dict or None if unable to extract.
"""
referer = request.headers.get("referer") or request.headers.get("origin")
if not referer:
logger.debug("[STORE] No Referer/Origin header for shop API request")
logger.debug("[STORE] No Referer/Origin header for storefront API request")
return None
try:
@@ -287,7 +282,7 @@ class StoreContextManager:
)
# Method 1: Path-based detection from referer path
# /stores/wizamart/shop/products → wizamart
# /stores/wizamart/storefront/products → wizamart
if referer_path.startswith(("/stores/", "/store/")):
prefix = (
"/stores/" if referer_path.startswith("/stores/") else "/store/"
@@ -448,75 +443,10 @@ class StoreContextMiddleware(BaseHTTPMiddleware):
request.state.clean_path = request.url.path
return await call_next(request)
# Handle shop API routes specially - extract store from Referer header
if StoreContextManager.is_shop_api_request(request):
logger.debug(
f"[STORE] Shop API request detected: {request.url.path}",
extra={
"path": request.url.path,
"referer": request.headers.get("referer", ""),
},
)
store_context = StoreContextManager.extract_store_from_referer(request)
if store_context:
db_gen = get_db()
db = next(db_gen)
try:
store = StoreContextManager.get_store_from_context(
db, store_context
)
if store:
request.state.store = store
request.state.store_context = store_context
request.state.clean_path = request.url.path
logger.debug(
"[STORE_CONTEXT] Store detected from Referer for shop API",
extra={
"store_id": store.id,
"store_name": store.name,
"store_subdomain": store.subdomain,
"detection_method": store_context.get(
"detection_method"
),
"api_path": request.url.path,
"referer": store_context.get("referer", ""),
},
)
else:
logger.warning(
"[WARNING] Store context from Referer but store not found",
extra={
"context": store_context,
"detection_method": store_context.get(
"detection_method"
),
"api_path": request.url.path,
},
)
request.state.store = None
request.state.store_context = store_context
request.state.clean_path = request.url.path
finally:
db.close()
else:
logger.warning(
"[STORE] Shop API request without Referer header",
extra={"path": request.url.path},
)
request.state.store = None
request.state.store_context = None
request.state.clean_path = request.url.path
return await call_next(request)
# Skip store detection for other API routes (admin API, store API have store_id in URL)
# Skip store detection for API routes (admin API, store API have store_id in URL)
if StoreContextManager.is_api_request(request):
logger.debug(
f"[STORE] Skipping store detection for non-shop API: {request.url.path}",
f"[STORE] Skipping store detection for non-storefront API: {request.url.path}",
extra={"path": request.url.path, "reason": "api"},
)
request.state.store = None