openauth_core/options/
rate_limit.rs1use std::fmt;
2use std::sync::Arc;
3
4use http::Request;
5
6use crate::error::OpenAuthError;
7
8#[derive(Clone)]
10pub struct RateLimitOptions {
11 pub enabled: Option<bool>,
12 pub window: u64,
13 pub max: u64,
14 pub storage: RateLimitStorageOption,
15 pub custom_rules: Vec<RateLimitPathRule>,
16 pub dynamic_rules: Vec<DynamicRateLimitPathRule>,
17 pub custom_storage: Option<Arc<dyn RateLimitStorage>>,
18}
19
20impl Default for RateLimitOptions {
21 fn default() -> Self {
22 Self {
23 enabled: None,
24 window: 10,
25 max: 100,
26 storage: RateLimitStorageOption::Memory,
27 custom_rules: Vec::new(),
28 dynamic_rules: Vec::new(),
29 custom_storage: None,
30 }
31 }
32}
33
34impl fmt::Debug for RateLimitOptions {
35 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
36 formatter
37 .debug_struct("RateLimitOptions")
38 .field("enabled", &self.enabled)
39 .field("window", &self.window)
40 .field("max", &self.max)
41 .field("storage", &self.storage)
42 .field("custom_rules", &self.custom_rules)
43 .field("dynamic_rules", &self.dynamic_rules)
44 .field(
45 "custom_storage",
46 &self.custom_storage.as_ref().map(|_| "<custom-storage>"),
47 )
48 .finish()
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct RateLimitRule {
54 pub window: u64,
55 pub max: u64,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct RateLimitPathRule {
60 pub path: String,
61 pub rule: Option<RateLimitRule>,
62}
63
64pub trait RateLimitRuleProvider: Send + Sync + 'static {
65 fn resolve(
66 &self,
67 request: &Request<Vec<u8>>,
68 current_rule: &RateLimitRule,
69 ) -> Result<Option<RateLimitRule>, OpenAuthError>;
70}
71
72impl<F> RateLimitRuleProvider for F
73where
74 F: Fn(&Request<Vec<u8>>, &RateLimitRule) -> Result<Option<RateLimitRule>, OpenAuthError>
75 + Send
76 + Sync
77 + 'static,
78{
79 fn resolve(
80 &self,
81 request: &Request<Vec<u8>>,
82 current_rule: &RateLimitRule,
83 ) -> Result<Option<RateLimitRule>, OpenAuthError> {
84 self(request, current_rule)
85 }
86}
87
88#[derive(Clone)]
89pub struct DynamicRateLimitPathRule {
90 pub path: String,
91 pub provider: Arc<dyn RateLimitRuleProvider>,
92}
93
94impl DynamicRateLimitPathRule {
95 pub fn new<P>(path: impl Into<String>, provider: P) -> Self
96 where
97 P: RateLimitRuleProvider,
98 {
99 Self {
100 path: path.into(),
101 provider: Arc::new(provider),
102 }
103 }
104}
105
106impl fmt::Debug for DynamicRateLimitPathRule {
107 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
108 formatter
109 .debug_struct("DynamicRateLimitPathRule")
110 .field("path", &self.path)
111 .field("provider", &"<request-aware>")
112 .finish()
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
118pub struct RateLimitRecord {
119 pub key: String,
120 pub count: u64,
121 pub last_request: i64,
122}
123
124pub trait RateLimitStorage: Send + Sync + 'static {
126 fn get(&self, key: &str) -> Result<Option<RateLimitRecord>, OpenAuthError>;
127 fn set(
128 &self,
129 key: &str,
130 value: RateLimitRecord,
131 ttl_seconds: u64,
132 update: bool,
133 ) -> Result<(), OpenAuthError>;
134}
135
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138pub enum RateLimitStorageOption {
139 Memory,
140 Database,
141 SecondaryStorage,
142}