aws_smithy_http_server/
config.rs1use crate::settings::{
9 DEFAULT_EVENT_STREAM_IDLE_TIMEOUT, DEFAULT_EVENT_STREAM_INITIAL_MESSAGE_TIMEOUT,
10 DEFAULT_EVENT_STREAM_MESSAGE_COMPLETION_TIMEOUT,
11};
12use crate::settings::{DEFAULT_REQUEST_BODY_MAX_BYTES, DEFAULT_REQUEST_BODY_READ_POLL_BUDGET};
13use aws_smithy_schema::ShapeId;
14use std::{collections::HashMap, num::NonZeroUsize, time::Duration};
15
16#[derive(Clone, Debug)]
18#[non_exhaustive]
19pub struct ServiceConfig {
20 pub header_read_timeout: Option<Duration>,
25 pub request_body: ServiceRequestBodyConfig,
30 pub event_stream: ServiceEventStreamConfig,
32}
33
34impl Default for ServiceConfig {
35 fn default() -> Self {
36 Self {
37 header_read_timeout: Some(crate::settings::DEFAULT_HEADER_READ_TIMEOUT),
38 request_body: ServiceRequestBodyConfig::default(),
39 event_stream: ServiceEventStreamConfig::default(),
40 }
41 }
42}
43
44impl ServiceConfig {
45 pub fn with_header_read_timeout(mut self, timeout: Option<Duration>) -> Self {
47 self.header_read_timeout = timeout.filter(|timeout| !timeout.is_zero());
48 self
49 }
50
51 pub fn with_event_stream(mut self, event_stream: ServiceEventStreamConfig) -> Self {
52 self.event_stream = event_stream;
53 self
54 }
55
56 pub fn with_request_body(mut self, request_body: ServiceRequestBodyConfig) -> Self {
58 self.request_body = request_body;
59 self
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64#[non_exhaustive]
65pub struct RequestBodyCollectionConfig {
66 pub max_bytes: Option<NonZeroUsize>,
67 pub read_timeout: Option<Duration>,
68 pub read_poll_budget: Option<NonZeroUsize>,
71}
72
73impl Default for RequestBodyCollectionConfig {
74 fn default() -> Self {
75 Self {
76 max_bytes: NonZeroUsize::new(DEFAULT_REQUEST_BODY_MAX_BYTES),
77 read_timeout: None,
78 read_poll_budget: NonZeroUsize::new(DEFAULT_REQUEST_BODY_READ_POLL_BUDGET),
79 }
80 }
81}
82
83#[derive(Debug, Default, Clone)]
84#[non_exhaustive]
85pub struct ServiceRequestBodyConfig {
86 pub global: RequestBodyCollectionConfig,
87 pub per_operation: HashMap<String, RequestBodyCollectionConfig>,
88}
89
90impl RequestBodyCollectionConfig {
91 pub fn with_max_bytes(mut self, max_bytes: Option<NonZeroUsize>) -> Self {
93 self.max_bytes = max_bytes;
94 self
95 }
96
97 pub fn with_read_timeout(mut self, read_timeout: Option<Duration>) -> Self {
99 self.read_timeout = read_timeout;
100 self
101 }
102
103 pub fn with_read_poll_budget(mut self, read_poll_budget: Option<NonZeroUsize>) -> Self {
105 self.read_poll_budget = read_poll_budget;
106 self
107 }
108}
109
110impl ServiceRequestBodyConfig {
111 pub fn with_global(mut self, global: RequestBodyCollectionConfig) -> Self {
113 self.global = global;
114 self
115 }
116
117 pub fn with_per_operation(mut self, per_operation: HashMap<String, RequestBodyCollectionConfig>) -> Self {
119 self.per_operation = per_operation;
120 self
121 }
122
123 pub fn for_routing(&self) -> RequestBodyCollectionConfig {
126 let mut maximum = self.global;
127 for config in self.per_operation.values() {
128 maximum.max_bytes = match (maximum.max_bytes, config.max_bytes) {
129 (Some(left), Some(right)) => Some(left.max(right)),
130 _ => None,
131 };
132 maximum.read_timeout = match (maximum.read_timeout, config.read_timeout) {
133 (Some(left), Some(right)) => Some(left.max(right)),
134 _ => None,
135 };
136 maximum.read_poll_budget = match (maximum.read_poll_budget, config.read_poll_budget) {
137 (Some(left), Some(right)) => Some(left.max(right)),
138 _ => None,
139 };
140 }
141 maximum
142 }
143
144 pub fn for_operation(&self, operation: &ShapeId<'_>) -> RequestBodyCollectionConfig {
145 self.per_operation
146 .get(operation.as_str())
147 .copied()
148 .unwrap_or(self.global)
149 }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159#[non_exhaustive]
160pub struct EventStreamTimeoutConfig {
161 pub initial_message: Option<Duration>,
164 pub message_completion: Option<Duration>,
167 pub idle: Option<Duration>,
170}
171
172impl Default for EventStreamTimeoutConfig {
173 fn default() -> Self {
174 Self {
175 initial_message: DEFAULT_EVENT_STREAM_INITIAL_MESSAGE_TIMEOUT,
176 message_completion: DEFAULT_EVENT_STREAM_MESSAGE_COMPLETION_TIMEOUT,
177 idle: DEFAULT_EVENT_STREAM_IDLE_TIMEOUT,
178 }
179 }
180}
181
182impl EventStreamTimeoutConfig {
183 pub fn with_initial_message(mut self, timeout: Option<Duration>) -> Self {
184 self.initial_message = timeout.filter(|timeout| !timeout.is_zero());
185 self
186 }
187
188 pub fn with_message_completion(mut self, timeout: Option<Duration>) -> Self {
189 self.message_completion = timeout.filter(|timeout| !timeout.is_zero());
190 self
191 }
192
193 pub fn with_idle(mut self, timeout: Option<Duration>) -> Self {
194 self.idle = timeout.filter(|timeout| !timeout.is_zero());
195 self
196 }
197}
198
199#[derive(Debug, Default, Clone)]
201#[non_exhaustive]
202pub struct ServiceEventStreamConfig {
203 pub global: EventStreamTimeoutConfig,
204 pub per_operation: HashMap<String, EventStreamTimeoutConfig>,
205}
206
207impl ServiceEventStreamConfig {
208 pub fn with_global(mut self, global: EventStreamTimeoutConfig) -> Self {
209 self.global = global;
210 self
211 }
212
213 pub fn with_per_operation(mut self, per_operation: HashMap<String, EventStreamTimeoutConfig>) -> Self {
214 self.per_operation = per_operation;
215 self
216 }
217
218 pub fn for_operation(&self, operation: &ShapeId<'_>) -> EventStreamTimeoutConfig {
219 self.per_operation
220 .get(operation.as_str())
221 .copied()
222 .unwrap_or(self.global)
223 }
224}