Use Case
extract_client_info() is an HTTP parsing helper currently placed in service layer (src/audit/service.py). It belongs in the HTTP layer where it's used.
Proposed Solution
Move extract_client_info() to src/http/utils.py:
# Move from src/audit/service.py:81-88 to src/http/utils.py
def extract_client_info(request: Request) -> tuple[str | None, str | None]:
user_agent = request.headers.get("user-agent")
forwarded_for = request.headers.get("x-forwarded-for")
ip = forwarded_for.split(",")[0].strip() if forwarded_for else (request.client.host if request.client else None)
return user_agent, ip
# Update imports in src/http/routers/auth.py
from src.http.utils import extract_client_info
Why Not Inline
Inlining across 5 call sites creates unnecessary duplication for logic that's always needed in auth handlers.
Why Not Pass Request to Service
Passing Request to audit_service.log() would couple the service layer to HTTP framework, violating layer separation.
Implementation Notes
- Move:
src/audit/service.py:81-88 → src/http/utils.py
- Update:
src/http/routers/auth.py import statement
- Remove:
extract_client_info from src/audit/service.py exports
Use Case
extract_client_info()is an HTTP parsing helper currently placed in service layer (src/audit/service.py). It belongs in the HTTP layer where it's used.Proposed Solution
Move
extract_client_info()tosrc/http/utils.py:Why Not Inline
Inlining across 5 call sites creates unnecessary duplication for logic that's always needed in auth handlers.
Why Not Pass Request to Service
Passing
Requesttoaudit_service.log()would couple the service layer to HTTP framework, violating layer separation.Implementation Notes
src/audit/service.py:81-88→src/http/utils.pysrc/http/routers/auth.pyimport statementextract_client_infofromsrc/audit/service.pyexports