1use crate::parser::Http1Parser;
10use crate::types::{Http1Config, Http1Error, HttpRequest};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum Http1ConnectionState {
15 Waiting,
17 ReadingRequest,
19 ReadingHeaders,
21 ReadingBody,
23 Processing,
25 SendingResponse,
27 Closing,
29 Closed,
31}
32
33#[derive(Debug)]
35pub struct Http1Connection {
36 state: Http1ConnectionState,
37 parser: Http1Parser,
38 current_request: Option<HttpRequest>,
40 keep_alive: bool,
42 requests_handled: u64,
44 closed: bool,
46 last_activity_ms: u64,
48 time_initialized: bool,
50}
51
52impl Http1Connection {
53 #[inline]
55 pub fn new(config: Http1Config) -> Self {
56 Self {
57 keep_alive: config.keep_alive,
58 parser: Http1Parser::new(config),
59 state: Http1ConnectionState::Waiting,
60 current_request: None,
61 requests_handled: 0,
62 closed: false,
63 last_activity_ms: 0,
64 time_initialized: false,
65 }
66 }
67
68 #[inline]
70 pub fn state(&self) -> Http1ConnectionState {
71 self.state
72 }
73
74 #[inline]
76 pub fn is_closed(&self) -> bool {
77 self.closed
78 }
79
80 pub fn on_data(&mut self, data: &[u8]) -> Result<(Option<HttpRequest>, usize), Http1Error> {
87 if self.closed {
88 return Err(Http1Error::ConnectionClosed);
89 }
90
91 if !data.is_empty() && self.time_initialized {
96 self.parser.note_activity(self.last_activity_ms);
97 }
98
99 let (req, consumed) = match self.parser.feed(data) {
100 Ok(v) => v,
101 Err(e) => {
102 self.on_error(&e);
103 return Err(e);
104 }
105 };
106
107 if let Some(mut req) = req {
108 if !req.keep_alive {
110 self.keep_alive = false;
111 }
112 if req.chunked {
119 self.state = Http1ConnectionState::Processing;
121 } else if let Some(len) = req.content_length {
122 if len == 0 {
123 self.state = Http1ConnectionState::Processing;
124 } else if !req.body.is_empty() && req.body.len() as u64 == len {
125 self.state = Http1ConnectionState::Processing;
127 } else {
128 self.state = Http1ConnectionState::ReadingBody;
130 }
131 } else if req.line.method.as_ref() == "POST" || req.line.method.as_ref() == "PUT" {
132 req.content_length = Some(0);
134 self.state = Http1ConnectionState::Processing;
135 } else {
136 self.state = Http1ConnectionState::Processing;
137 }
138 self.current_request = Some(req);
139 self.requests_handled += 1;
140 Ok((self.current_request.clone(), consumed))
141 } else {
142 self.state = match self.parser.state() {
145 crate::parser::ParserState::WaitingRequest
146 | crate::parser::ParserState::ReadingRequest => Http1ConnectionState::ReadingRequest,
147 crate::parser::ParserState::ReadingHeaders => Http1ConnectionState::ReadingHeaders,
148 crate::parser::ParserState::ReadingBody
149 | crate::parser::ParserState::ReadingChunkSize
150 | crate::parser::ParserState::ReadingChunkData
151 | crate::parser::ParserState::ReadingChunkTrailer => Http1ConnectionState::ReadingBody,
152 crate::parser::ParserState::HeadersComplete => Http1ConnectionState::Processing,
153 crate::parser::ParserState::Error => Http1ConnectionState::Closed,
154 };
155 Ok((None, consumed))
156 }
157 }
158
159 pub fn body_complete(&mut self, body: Vec<u8>) {
161 if let Some(req) = self.current_request.as_mut() {
162 req.body = body;
163 self.state = Http1ConnectionState::Processing;
164 }
165 }
166
167 #[inline]
169 pub fn current_request(&self) -> Option<&HttpRequest> {
170 self.current_request.as_ref()
171 }
172
173 pub fn response_sent(&mut self) {
175 self.current_request = None;
176 if !self.keep_alive {
177 self.state = Http1ConnectionState::Closing;
178 self.closed = true;
179 } else {
180 self.parser.reset();
182 self.state = Http1ConnectionState::Waiting;
183 }
184 }
185
186 pub fn on_error(&mut self, _err: &Http1Error) {
188 self.state = Http1ConnectionState::Closing;
189 self.closed = true;
190 }
191
192 #[inline]
194 pub fn requests_handled(&self) -> u64 {
195 self.requests_handled
196 }
197
198 #[inline]
205 pub fn update_time(&mut self, now_ms: u64) {
206 self.last_activity_ms = now_ms;
207 self.time_initialized = true;
208 }
209
210 pub fn check_timeout(&mut self) -> Result<(), Http1Error> {
214 if self.closed {
215 return Ok(());
216 }
217 if let Err(e) = self.parser.check_idle_timeout(self.last_activity_ms) {
218 self.on_error(&e);
219 return Err(e);
220 }
221 Ok(())
222 }
223
224 pub fn close(&mut self) {
226 self.state = Http1ConnectionState::Closed;
227 self.closed = true;
228 }
229}
230
231impl Default for Http1Connection {
232 fn default() -> Self {
233 Self::new(Http1Config::new())
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240
241 #[test]
242 fn test_connection_basic() {
243 let mut conn = Http1Connection::new(Http1Config::new());
244 let input = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
245 let (req, _) = conn.on_data(input).unwrap();
246 assert!(req.is_some());
247 assert_eq!(conn.state(), Http1ConnectionState::Processing);
248 }
249
250 #[test]
251 fn test_connection_lifecycle() {
252 let mut conn = Http1Connection::new(Http1Config::new());
253 let input = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
254 conn.on_data(input).unwrap();
255 assert_eq!(conn.state(), Http1ConnectionState::Processing);
256
257 conn.response_sent();
258 assert_eq!(conn.state(), Http1ConnectionState::Waiting);
259 assert!(!conn.is_closed());
260 }
261
262 #[test]
263 fn test_connection_close() {
264 let mut conn = Http1Connection::new(Http1Config::new());
265 let input =
266 b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
267 conn.on_data(input).unwrap();
268 conn.response_sent();
269 assert!(conn.is_closed());
270 }
271
272 #[test]
273 fn test_connection_error_cases() {
274 let mut conn = Http1Connection::new(Http1Config::new());
275 let r = conn.on_data(b"INV HTTP/1.1\r\nHost: x\r\n\r\n");
276 assert!(r.is_err());
277 assert!(conn.is_closed());
278 }
279
280 #[test]
281 fn test_connection_body_post() {
282 let mut conn = Http1Connection::new(Http1Config::new());
283 let input =
286 b"POST /api HTTP/1.1\r\nHost: example.com\r\nContent-Length: 5\r\n\r\nhello";
287 let (req, _) = conn.on_data(input).unwrap();
288 let req = req.unwrap();
289 assert_eq!(req.content_length, Some(5));
290 assert_eq!(req.body, b"hello");
291 assert_eq!(conn.state(), Http1ConnectionState::Processing);
292 }
293
294 #[test]
295 fn test_connection_state_variants() {
296 let states = [
297 Http1ConnectionState::Waiting,
298 Http1ConnectionState::ReadingRequest,
299 Http1ConnectionState::ReadingHeaders,
300 Http1ConnectionState::ReadingBody,
301 Http1ConnectionState::Processing,
302 Http1ConnectionState::SendingResponse,
303 Http1ConnectionState::Closing,
304 Http1ConnectionState::Closed,
305 ];
306 for (i, s) in states.iter().enumerate() {
307 assert_eq!(*s, states[i]);
308 }
309 assert_ne!(Http1ConnectionState::Waiting, Http1ConnectionState::Closed);
310 }
311
312 #[test]
313 fn test_connection_default() {
314 let conn = Http1Connection::default();
315 assert_eq!(conn.state(), Http1ConnectionState::Waiting);
316 assert!(!conn.is_closed());
317 assert_eq!(conn.requests_handled(), 0);
318 }
319
320 #[test]
321 fn test_connection_keep_alive_multiple_requests() {
322 let mut conn = Http1Connection::new(Http1Config::new());
323 let input1 = b"GET /1 HTTP/1.1\r\nHost: example.com\r\n\r\n";
324 let (req1, _) = conn.on_data(input1).unwrap();
325 assert!(req1.is_some());
326 assert_eq!(conn.requests_handled(), 1);
327
328 conn.response_sent();
329 assert_eq!(conn.state(), Http1ConnectionState::Waiting);
330
331 let input2 = b"GET /2 HTTP/1.1\r\nHost: example.com\r\n\r\n";
332 let (req2, _) = conn.on_data(input2).unwrap();
333 assert!(req2.is_some());
334 assert_eq!(conn.requests_handled(), 2);
335 }
336
337 #[test]
338 fn test_connection_closed_rejects_data() {
339 let mut conn = Http1Connection::new(Http1Config::new());
340 conn.close();
341 assert!(conn.is_closed());
342 assert_eq!(conn.state(), Http1ConnectionState::Closed);
343
344 let input = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
345 let r = conn.on_data(input);
346 assert!(r.is_err());
347 assert!(matches!(r.unwrap_err(), Http1Error::ConnectionClosed));
348 }
349
350 #[test]
351 fn test_connection_current_request() {
352 let mut conn = Http1Connection::new(Http1Config::new());
353 assert!(conn.current_request().is_none());
354
355 let input = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
356 conn.on_data(input).unwrap();
357 assert!(conn.current_request().is_some());
358 assert_eq!(conn.current_request().unwrap().line.method.as_ref(), "GET");
359 }
360
361 #[test]
362 fn test_connection_chunked_body_state() {
363 let mut conn = Http1Connection::new(Http1Config::new());
364 let input = b"POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n0\r\n\r\n";
366 let (req, _) = conn.on_data(input).unwrap();
367 assert!(req.is_some());
368 let req = req.unwrap();
369 assert_eq!(conn.state(), Http1ConnectionState::Processing);
370 assert_eq!(req.body, b"Hello");
371 }
372
373 #[test]
374 fn test_connection_chunked_body_partial() {
375 let mut conn = Http1Connection::new(Http1Config::new());
376 let part1 = b"POST /upload HTTP/1.1\r\nHost: example.com\r\nTransfer-Encoding: chunked\r\n\r\n";
378 let (req, _) = conn.on_data(part1).unwrap();
379 assert!(req.is_none());
380 assert_eq!(conn.state(), Http1ConnectionState::ReadingBody);
381
382 let part2 = b"5\r\nHello\r\n0\r\n\r\n";
384 let (req, _) = conn.on_data(part2).unwrap();
385 assert!(req.is_some());
386 assert_eq!(conn.state(), Http1ConnectionState::Processing);
387 assert_eq!(req.unwrap().body, b"Hello");
388 }
389
390 #[test]
391 fn test_connection_zero_content_length() {
392 let mut conn = Http1Connection::new(Http1Config::new());
393 let input = b"POST /api HTTP/1.1\r\nHost: example.com\r\nContent-Length: 0\r\n\r\n";
394 let (req, _) = conn.on_data(input).unwrap();
395 assert!(req.is_some());
396 assert_eq!(conn.state(), Http1ConnectionState::Processing);
397 }
398
399 #[test]
400 fn test_connection_put_method() {
401 let mut conn = Http1Connection::new(Http1Config::new());
402 let input =
404 b"PUT /resource HTTP/1.1\r\nHost: example.com\r\nContent-Length: 5\r\n\r\nworld";
405 let (req, _) = conn.on_data(input).unwrap();
406 let req = req.unwrap();
407 assert_eq!(req.line.method.as_ref(), "PUT");
408 assert_eq!(req.body, b"world");
409 assert_eq!(conn.state(), Http1ConnectionState::Processing);
410 }
411
412 #[test]
413 fn test_connection_head_method() {
414 let mut conn = Http1Connection::new(Http1Config::new());
415 let input = b"HEAD / HTTP/1.1\r\nHost: example.com\r\n\r\n";
416 let (req, _) = conn.on_data(input).unwrap();
417 assert!(req.is_some());
418 assert_eq!(req.unwrap().line.method.as_ref(), "HEAD");
419 assert_eq!(conn.state(), Http1ConnectionState::Processing);
420 }
421
422 #[test]
423 fn test_connection_on_error_closes_connection() {
424 let mut conn = Http1Connection::new(Http1Config::new());
425 conn.on_error(&Http1Error::SyntaxError("test".into()));
426 assert!(conn.is_closed());
427 assert_eq!(conn.state(), Http1ConnectionState::Closing);
428 }
429
430 #[test]
431 fn test_connection_body_complete_no_current_request() {
432 let mut conn = Http1Connection::new(Http1Config::new());
433 conn.body_complete(b"test".to_vec());
434 assert_eq!(conn.state(), Http1ConnectionState::Waiting);
435 }
436
437 #[test]
438 fn test_connection_response_sent_clears_request() {
439 let mut conn = Http1Connection::new(Http1Config::new());
440 let input = b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
441 conn.on_data(input).unwrap();
442 assert!(conn.current_request().is_some());
443 conn.response_sent();
444 assert!(conn.current_request().is_none());
445 }
446
447 #[test]
448 fn test_connection_closing_state() {
449 let mut conn = Http1Connection::new(Http1Config::new());
450 let input = b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
451 conn.on_data(input).unwrap();
452 conn.response_sent();
453 assert_eq!(conn.state(), Http1ConnectionState::Closing);
454 assert!(conn.is_closed());
455 }
456
457 #[test]
458 fn test_connection_debug_format() {
459 let conn = Http1Connection::new(Http1Config::new());
460 let s = format!("{:?}", conn);
461 assert!(!s.is_empty());
462 }
463
464 #[test]
465 fn test_connection_idle_timeout_during_body_read() {
466 let config = Http1Config::new().with_idle_timeout_ms(30_000);
468 let mut conn = Http1Connection::new(config);
469 conn.update_time(0);
470 let (req, _) = conn
472 .on_data(b"POST / HTTP/1.1\r\nHost: example.com\r\nContent-Length: 10\r\n\r\n")
473 .unwrap();
474 assert!(req.is_none());
475 assert_eq!(conn.state(), Http1ConnectionState::ReadingBody);
476 conn.update_time(30_001);
478 let r = conn.check_timeout();
479 assert!(matches!(r, Err(Http1Error::IdleTimeout)), "实际 {r:?}");
480 assert!(conn.is_closed());
481 }
482
483 #[test]
484 fn test_connection_body_activity_prevents_timeout() {
485 let config = Http1Config::new().with_idle_timeout_ms(30_000);
487 let mut conn = Http1Connection::new(config);
488 conn.update_time(0);
489 let (req, _) = conn
490 .on_data(b"POST / HTTP/1.1\r\nHost: example.com\r\nContent-Length: 6\r\n\r\nhe")
491 .unwrap();
492 assert!(req.is_none());
493 conn.update_time(20_000);
495 let (req, _) = conn.on_data(b"ll").unwrap();
496 assert!(req.is_none());
497 conn.update_time(45_000);
499 assert!(conn.check_timeout().is_ok(), "活跃刷新后不得超时");
500 let (req, _) = conn.on_data(b"lo").unwrap();
502 assert!(req.is_some());
503 }
504}