fastapi-commons 0.6.6__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {fastapi_commons-0.6.6/src/fastapi_commons.egg-info → fastapi_commons-0.7.0}/PKG-INFO +1 -1
  2. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/middleware/prometheus.py +37 -6
  3. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0/src/fastapi_commons.egg-info}/PKG-INFO +1 -1
  4. fastapi_commons-0.7.0/src/fastapi_commons.egg-info/scm_version.json +8 -0
  5. fastapi_commons-0.6.6/src/fastapi_commons.egg-info/scm_version.json +0 -8
  6. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.coveragerc +0 -0
  7. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.env_template +0 -0
  8. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.github/workflows/checks.yml +0 -0
  9. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.github/workflows/python-publish.yaml +0 -0
  10. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.github/workflows/release-on-tag-push.yml +0 -0
  11. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.gitignore +0 -0
  12. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.pre-commit-config.yaml +0 -0
  13. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/.python-version +0 -0
  14. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/AUTHORS.rst +0 -0
  15. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/CHANGELOG.rst +0 -0
  16. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/LICENSE +0 -0
  17. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/README.md +0 -0
  18. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/README.rst +0 -0
  19. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/pyproject.toml +0 -0
  20. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/setup.cfg +0 -0
  21. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/__init__.py +0 -0
  22. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/auth.py +0 -0
  23. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/conf.py +0 -0
  24. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/handlers.py +0 -0
  25. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/helpers.py +0 -0
  26. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/instrumentation.py +0 -0
  27. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/log/__init__.py +0 -0
  28. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/log/filters.py +0 -0
  29. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/middleware/__init__.py +0 -0
  30. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/middleware/correlation_id.py +0 -0
  31. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons/middleware/log_context.py +0 -0
  32. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons.egg-info/SOURCES.txt +0 -0
  33. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons.egg-info/dependency_links.txt +0 -0
  34. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons.egg-info/requires.txt +0 -0
  35. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons.egg-info/scm_file_list.json +0 -0
  36. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/src/fastapi_commons.egg-info/top_level.txt +0 -0
  37. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/tests/__init__.py +0 -0
  38. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/tests/conftest.py +0 -0
  39. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/tests/unit/__init__.py +0 -0
  40. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/tests/unit/test_poc.py +0 -0
  41. {fastapi_commons-0.6.6 → fastapi_commons-0.7.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-commons
3
- Version: 0.6.6
3
+ Version: 0.7.0
4
4
  Summary: Re-usable FastAPI code
5
5
  Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
6
6
  License-Expression: GPL-3.0
@@ -1,5 +1,7 @@
1
1
  import time
2
+ from collections.abc import Sequence
2
3
 
4
+ from fastapi.routing import APIRoute, _IncludedRouter
3
5
  from opentelemetry import trace
4
6
  from prometheus_client import REGISTRY, Counter, Gauge, Histogram
5
7
  from prometheus_client.openmetrics.exposition import (
@@ -9,9 +11,9 @@ from prometheus_client.openmetrics.exposition import (
9
11
  from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
10
12
  from starlette.requests import Request
11
13
  from starlette.responses import Response
12
- from starlette.routing import Match
14
+ from starlette.routing import BaseRoute, Match, Mount
13
15
  from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
14
- from starlette.types import ASGIApp
16
+ from starlette.types import ASGIApp, Scope
15
17
 
16
18
  INFO = Gauge('fastapi_app_info', 'FastAPI application information.', ['app_name'])
17
19
  REQUESTS = Counter(
@@ -41,6 +43,37 @@ REQUESTS_IN_PROGRESS = Gauge(
41
43
  )
42
44
 
43
45
 
46
+ def _join_paths(prefix: str, path: str) -> str:
47
+ if not prefix:
48
+ return path
49
+ return f'{prefix.rstrip("/")}/{path.lstrip("/")}'
50
+
51
+
52
+ def _resolve_route_path(routes: Sequence[BaseRoute], scope: Scope) -> str | None:
53
+ """Resolve the templated path of the route matching ``scope``."""
54
+ for route in routes:
55
+ match, _ = route.matches(scope)
56
+
57
+ if match is not Match.FULL:
58
+ continue
59
+
60
+ if isinstance(route, _IncludedRouter):
61
+ prefix = route.include_context.prefix or ''
62
+ stripped_path = scope['path'][len(prefix) :]
63
+ sub_scope = {**scope, 'path': stripped_path} if prefix else scope
64
+ sub_path = _resolve_route_path(route.original_router.routes, sub_scope)
65
+
66
+ if sub_path is not None:
67
+ return _join_paths(prefix, sub_path)
68
+
69
+ continue
70
+
71
+ if isinstance(route, (APIRoute, Mount)):
72
+ return route.path
73
+
74
+ return None
75
+
76
+
44
77
  class PrometheusMiddleware(BaseHTTPMiddleware):
45
78
  def __init__(self, app: ASGIApp, app_name: str = 'fastapi-app') -> None:
46
79
  super().__init__(app)
@@ -86,10 +119,8 @@ class PrometheusMiddleware(BaseHTTPMiddleware):
86
119
 
87
120
  @staticmethod
88
121
  def get_path(request: Request) -> tuple[str, bool]:
89
- for route in request.app.routes:
90
- match, _ = route.matches(request.scope)
91
- if match == Match.FULL:
92
- return route.path, True
122
+ if path := _resolve_route_path(request.app.routes, request.scope):
123
+ return path, True
93
124
 
94
125
  return request.url.path, False
95
126
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-commons
3
- Version: 0.6.6
3
+ Version: 0.7.0
4
4
  Summary: Re-usable FastAPI code
5
5
  Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
6
6
  License-Expression: GPL-3.0
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.7.0",
3
+ "distance": 0,
4
+ "node": "ge636e90f0e45473d573f81290b42ab0ed3dc2b5d",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-07-20"
8
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.6.6",
3
- "distance": 0,
4
- "node": "g59406832b3c5d302e5a82928d843e7d978f9b58b",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-07-19"
8
- }
File without changes
File without changes