cat_gateway/service/common/types/headers/
retry_after.rs1use std::{borrow::Cow, fmt::Display};
6
7use chrono::{DateTime, Utc};
8use poem::http::HeaderValue;
9use poem_openapi::{
10 registry::{MetaSchema, MetaSchemaRef},
11 types::{ToHeader, Type},
12};
13use serde_json::Value;
14
15#[derive(Debug)]
17#[allow(dead_code)] pub(crate) enum RetryAfterHeader {
19 Date(DateTime<Utc>),
21 Seconds(u64),
23}
24
25#[derive(Debug)]
29#[allow(dead_code)] pub(crate) enum RetryAfterOption {
31 Default,
33 None,
35 Some(RetryAfterHeader),
37}
38
39impl Display for RetryAfterHeader {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 RetryAfterHeader::Date(date_time) => {
43 let http_date = date_time.format("%a, %d %b %Y %T GMT").to_string();
44 write!(f, "{http_date}")
45 },
46 RetryAfterHeader::Seconds(secs) => write!(f, "{secs}"),
47 }
48 }
49}
50
51impl Default for RetryAfterHeader {
52 fn default() -> Self {
53 Self::Seconds(300)
54 }
55}
56
57impl Type for RetryAfterHeader {
58 type RawElementValueType = Self;
59 type RawValueType = Self;
60
61 const IS_REQUIRED: bool = true;
62
63 fn name() -> Cow<'static, str> {
64 "string(http-date || integer)".into()
65 }
66
67 fn schema_ref() -> MetaSchemaRef {
68 MetaSchemaRef::Inline(Box::new(MetaSchema::new_with_format(
69 "string",
70 "http-date || integer",
71 )))
72 .merge(MetaSchema {
73 title: Some("Retry-After Header".to_owned()),
74 description: Some(
75 "Http Date or Interval in seconds.
76Valid formats:
77
78* `Retry-After: <http-date>`
79* `Retry-After: <delay-seconds>`
80
81See: <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After>",
82 ),
83 example: Some(Value::String("300".to_string())),
84 ..poem_openapi::registry::MetaSchema::ANY
85 })
86 }
87
88 fn as_raw_value(&self) -> Option<&Self::RawValueType> {
89 Some(self)
90 }
91
92 fn raw_element_iter<'a>(
93 &'a self,
94 ) -> Box<dyn Iterator<Item = &'a Self::RawElementValueType> + 'a> {
95 Box::new(self.as_raw_value().into_iter())
96 }
97}
98
99impl ToHeader for RetryAfterHeader {
100 fn to_header(&self) -> Option<HeaderValue> {
101 HeaderValue::from_str(&self.to_string()).ok()
102 }
103}