From a75099e3701ba5e4bf14d35740d446ac8e17d2a4 Mon Sep 17 00:00:00 2001 From: Stanislav Zmiev Date: Tue, 5 Mar 2024 20:44:26 +0400 Subject: [PATCH] Provide more extensibility for header-routing defaults --- CHANGELOG.md | 6 ++++++ cadwyn/applications.py | 1 + cadwyn/routing.py | 15 ++++++++++----- pyproject.toml | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f20845c..28a686d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ Please follow [the Keep a Changelog standard](https://keepachangelog.com/en/1.0. ## [Unreleased] +## [3.11.0] + +### Changed + +* Header router is no longer reliant on the API version header -- now it simply takes the API version from the `VersionBundle.api_version_var`, thus making it easy for someone to extend header routing and set their own rules for how the default version is chosen + ## [3.10.1] ### Fixed diff --git a/cadwyn/applications.py b/cadwyn/applications.py index e2fff706..96183eb6 100644 --- a/cadwyn/applications.py +++ b/cadwyn/applications.py @@ -127,6 +127,7 @@ def __init__( deprecated=deprecated, responses=responses, api_version_header_name=api_version_header_name, + api_version_var=self.versions.api_version_var, lifespan=lifespan, ) self.docs_url = docs_url diff --git a/cadwyn/routing.py b/cadwyn/routing.py index 6f067b52..82a173ed 100644 --- a/cadwyn/routing.py +++ b/cadwyn/routing.py @@ -1,6 +1,7 @@ import bisect from collections import OrderedDict from collections.abc import Sequence +from contextvars import ContextVar from datetime import date from functools import cached_property from logging import getLogger @@ -35,11 +36,18 @@ class _RootHeaderAPIRouter(APIRouter): matched to the higher versioned route """ - def __init__(self, *args: Any, api_version_header_name: str, **kwargs: Any): + def __init__( + self, + *args: Any, + api_version_header_name: str, + api_version_var: ContextVar[date] | ContextVar[date | None], + **kwargs: Any, + ): super().__init__(*args, **kwargs) self.versioned_routes: dict[date, list[BaseRoute]] = {} self.unversioned_routes: list[BaseRoute] = [] self.api_version_header_name = api_version_header_name.lower() + self.api_version_var = api_version_var @cached_property def sorted_versioned_routes(self): @@ -90,10 +98,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: await self.lifespan(scope, receive, send) return - request_headers = dict(scope["headers"]) - header_value = request_headers.get(self.api_version_header_name.encode(), b"").decode() - if header_value: - header_value = date.fromisoformat(header_value) + header_value = self.api_version_var.get(None) # if header_value is None, then it's an unversioned request and we need to use the unversioned routes # if there will be a value, we search for the most suitable version diff --git a/pyproject.toml b/pyproject.toml index 8adfc7a5..35b182c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cadwyn" -version = "3.10.1" +version = "3.11.0" description = "Production-ready community-driven modern Stripe-like API versioning in FastAPI" authors = ["Stanislav Zmiev "] license = "MIT"