auth_framework/api/
versioning.rs1use axum::{
6 extract::Request,
7 http::{HeaderMap, StatusCode},
8 middleware::Next,
9 response::Response,
10};
11
12#[derive(Debug, Clone, PartialEq, Default)]
14pub enum ApiVersion {
15 #[default]
16 V1,
17 V2,
18}
19
20impl ApiVersion {
21 pub fn from_header(headers: &HeaderMap) -> Option<Self> {
23 if let Some(accept) = headers.get("accept")
24 && let Ok(accept_str) = accept.to_str()
25 {
26 if accept_str.contains("application/vnd.authframework.v2+json") {
27 return Some(ApiVersion::V2);
28 } else if accept_str.contains("application/vnd.authframework.v1+json") {
29 return Some(ApiVersion::V1);
30 }
31 }
32 None
33 }
34
35 pub fn to_header_value(&self) -> &'static str {
37 match self {
38 ApiVersion::V1 => "application/vnd.authframework.v1+json",
39 ApiVersion::V2 => "application/vnd.authframework.v2+json",
40 }
41 }
42}
43
44pub async fn version_middleware(request: Request, next: Next) -> Result<Response, StatusCode> {
46 let headers = request.headers();
47 let version = ApiVersion::from_header(headers).unwrap_or_default();
48
49 let mut request = request;
51 request.extensions_mut().insert(version);
52
53 let mut response = next.run(request).await;
54
55 let default_version = ApiVersion::default();
57 let version = response
58 .extensions()
59 .get::<ApiVersion>()
60 .unwrap_or(&default_version)
61 .to_header_value();
62
63 response
64 .headers_mut()
65 .insert("api-version", version.parse().unwrap());
66
67 Ok(response)
68}
69
70pub fn get_api_version(request: &Request) -> ApiVersion {
72 request
73 .extensions()
74 .get::<ApiVersion>()
75 .cloned()
76 .unwrap_or_default()
77}
78
79