1use std::fmt;
2use std::fmt::{Display, Formatter};
3
4use crate::core::res_body::{ResBody, full};
5use crate::headers::{ContentType, Header, HeaderMap, HeaderMapExt};
6use crate::{Result, SilentError, State, StatusCode, header};
7use http::{Extensions, Version};
8use http_body::{Body, SizeHint};
9use serde::Serialize;
10use serde_json::Value;
11
12pub struct Response<B: Body = ResBody> {
18 pub(crate) status: StatusCode,
20 pub(crate) version: Version,
22 pub(crate) headers: HeaderMap,
24 pub(crate) body: B,
25 pub(crate) extensions: Extensions,
26 pub(crate) state: State,
27}
28
29impl fmt::Debug for Response {
30 #[inline]
31 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
32 writeln!(f, "{:?} {}\n{:?}", self.version, self.status, self.headers)
33 }
34}
35
36impl Display for Response {
37 #[inline]
38 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
39 fmt::Debug::fmt(self, f)
40 }
41}
42
43impl Response {
44 pub fn empty() -> Self {
46 Self {
47 status: StatusCode::OK,
48 headers: HeaderMap::new(),
49 version: Version::default(),
50 body: ResBody::None,
51 extensions: Extensions::default(),
52 state: State::default(),
53 }
54 }
55 #[inline]
57 pub fn status(&self) -> StatusCode {
58 self.status
59 }
60 #[inline]
62 pub fn take_body(&mut self) -> ResBody {
63 std::mem::replace(&mut self.body, ResBody::None)
64 }
65 #[inline]
66 pub fn redirect(url: &str) -> Result<Self> {
68 let mut res = Self::empty();
69 res.status = StatusCode::MOVED_PERMANENTLY;
70 res.headers.insert(
71 header::LOCATION,
72 url.parse().map_err(|e| {
73 SilentError::business_error(
74 StatusCode::INTERNAL_SERVER_ERROR,
75 format!("redirect error: {e}"),
76 )
77 })?,
78 );
79 Ok(res)
80 }
81 #[inline]
82 pub fn text(text: &str) -> Self {
84 let mut res = Self::empty();
85 res.set_typed_header(ContentType::text_utf8());
86 res.set_body(full(text.as_bytes().to_vec()));
87 res
88 }
89 #[inline]
90 pub fn html(html: &str) -> Self {
92 let mut res = Self::empty();
93 res.set_typed_header(ContentType::html());
94 res.set_body(full(html.as_bytes().to_vec()));
95 res
96 }
97 #[inline]
98 pub fn json<T: Serialize>(json: &T) -> Self {
100 let mut res = Self::empty();
101 res.set_typed_header(ContentType::json());
102 res.set_body(full(serde_json::to_vec(json).unwrap()));
103 res
104 }
105}
106
107impl<B: Body> Response<B> {
108 #[inline]
110 pub fn set_status(&mut self, status: StatusCode) {
111 self.status = status;
112 }
113 #[inline]
115 pub fn with_status(mut self, status: StatusCode) -> Self {
116 self.status = status;
117 self
118 }
119 #[inline]
121 pub fn set_body(&mut self, body: B) {
122 self.body = body;
123 }
124 #[inline]
126 pub fn with_body(mut self, body: B) -> Self {
127 self.body = body;
128 self
129 }
130 #[inline]
132 pub fn body(&self) -> &B {
133 &self.body
134 }
135 #[inline]
137 pub fn set_header(&mut self, key: header::HeaderName, value: header::HeaderValue) {
138 self.headers.insert(key, value);
139 }
140 #[inline]
142 pub fn with_header(mut self, key: header::HeaderName, value: header::HeaderValue) -> Self {
143 self.headers.insert(key, value);
144 self
145 }
146 #[inline]
147 pub fn extensions(&self) -> &Extensions {
149 &self.extensions
150 }
151 #[inline]
152 pub fn extensions_mut(&mut self) -> &mut Extensions {
154 &mut self.extensions
155 }
156
157 #[inline]
159 pub fn get_state<T: Send + Sync + 'static>(&self) -> Result<&T> {
160 self.state.get::<T>().ok_or(SilentError::ConfigNotFound)
161 }
162
163 #[inline]
165 pub fn get_state_uncheck<T: Send + Sync + 'static>(&self) -> &T {
166 self.state.get::<T>().unwrap()
167 }
168
169 #[inline]
171 pub fn state(&self) -> &State {
172 &self.state
173 }
174
175 #[inline]
177 pub fn state_mut(&mut self) -> &mut State {
178 &mut self.state
179 }
180
181 #[deprecated(since = "2.16.0", note = "请使用 get_state 代替")]
183 #[inline]
184 pub fn get_config<T: Send + Sync + 'static>(&self) -> Result<&T> {
185 self.get_state::<T>()
186 }
187
188 #[deprecated(since = "2.16.0", note = "请使用 get_state_uncheck 代替")]
190 #[inline]
191 pub fn get_config_uncheck<T: Send + Sync + 'static>(&self) -> &T {
192 self.get_state_uncheck::<T>()
193 }
194
195 #[deprecated(since = "2.16.0", note = "请使用 state() 代替")]
197 #[inline]
198 pub fn configs(&self) -> &State {
199 self.state()
200 }
201
202 #[deprecated(since = "2.16.0", note = "请使用 state_mut() 代替")]
204 #[inline]
205 pub fn configs_mut(&mut self) -> &mut State {
206 self.state_mut()
207 }
208 #[inline]
209 pub fn headers(&self) -> &HeaderMap {
211 &self.headers
212 }
213 #[inline]
214 pub fn headers_mut(&mut self) -> &mut HeaderMap {
216 &mut self.headers
217 }
218 #[inline]
219 pub fn content_length(&self) -> SizeHint {
221 self.body.size_hint()
222 }
223 #[inline]
224 pub fn set_typed_header<H>(&mut self, header: H)
226 where
227 H: Header,
228 {
229 self.headers.typed_insert(header);
230 }
231 #[inline]
232 pub fn with_typed_header<H>(mut self, header: H) -> Self
234 where
235 H: Header,
236 {
237 self.headers.typed_insert(header);
238 self
239 }
240
241 pub fn copy_from_response(&mut self, res: Response<B>) {
243 self.headers.extend(res.headers);
244 self.status = res.status;
245 self.extensions.extend(res.extensions);
246 self.set_body(res.body);
247 }
248}
249
250impl<S: Serialize> From<S> for Response {
251 fn from(value: S) -> Self {
252 match serde_json::to_value(&value).unwrap() {
253 Value::String(value) => Response::empty()
254 .with_typed_header(ContentType::json())
255 .with_body(full(value.as_bytes().to_vec())),
256 Value::Null => Response::empty().with_status(StatusCode::NO_CONTENT),
257 _ => Self::json(&value),
258 }
259 }
260}
261
262#[cfg(test)]
263mod tests {
264 use super::*;
265 use crate::core::response::Response;
266
267 #[test]
270 fn test_response_empty() {
271 let res = Response::empty();
272 assert_eq!(res.status(), StatusCode::OK);
273 assert_eq!(res.version, Version::default());
274 assert_eq!(res.headers().len(), 0);
275 }
276
277 #[test]
278 fn test_response_text() {
279 let res = Response::text("Hello, World!");
280 assert_eq!(res.status(), StatusCode::OK);
281 assert!(res.headers().get("content-type").is_some());
282 let content_type = res.headers().get("content-type").unwrap();
283 assert!(content_type.to_str().unwrap().contains("text/plain"));
284 }
285
286 #[test]
287 fn test_response_html() {
288 let res = Response::html("<html><body>Test</body></html>");
289 assert_eq!(res.status(), StatusCode::OK);
290 assert!(res.headers().get("content-type").is_some());
291 let content_type = res.headers().get("content-type").unwrap();
292 assert!(content_type.to_str().unwrap().contains("text/html"));
293 }
294
295 #[test]
296 fn test_response_json() {
297 let data = serde_json::json!({"key": "value"});
298 let res = Response::json(&data);
299 assert_eq!(res.status(), StatusCode::OK);
300 assert!(res.headers().get("content-type").is_some());
301 let content_type = res.headers().get("content-type").unwrap();
302 assert!(content_type.to_str().unwrap().contains("application/json"));
303 }
304
305 #[test]
306 fn test_response_json_with_struct() {
307 #[derive(Serialize)]
308 struct TestData {
309 name: String,
310 count: i32,
311 }
312 let data = TestData {
313 name: "test".to_string(),
314 count: 42,
315 };
316 let res = Response::json(&data);
317 assert_eq!(res.status(), StatusCode::OK);
318 assert!(res.headers().get("content-type").is_some());
319 }
320
321 #[test]
322 fn test_response_redirect_valid_url() {
323 let res = Response::redirect("https://example.com");
324 assert!(res.is_ok());
325 let res = res.unwrap();
326 assert_eq!(res.status(), StatusCode::MOVED_PERMANENTLY);
327 assert!(res.headers().get("location").is_some());
328 let location = res.headers().get("location").unwrap();
329 assert_eq!(location.to_str().unwrap(), "https://example.com");
330 }
331
332 #[test]
333 fn test_response_redirect_relative_url() {
334 let res = Response::redirect("/new-location");
335 assert!(res.is_ok());
336 let res = res.unwrap();
337 assert_eq!(res.status(), StatusCode::MOVED_PERMANENTLY);
338 assert!(res.headers().get("location").is_some());
339 }
340
341 #[test]
342 fn test_response_redirect_empty_url() {
343 let res = Response::redirect("");
344 assert!(res.is_ok());
346 let res = res.unwrap();
347 assert_eq!(res.status(), StatusCode::MOVED_PERMANENTLY);
348 }
349
350 #[test]
351 fn test_response_redirect_invalid_url() {
352 let res = Response::redirect("not a valid url");
353 assert!(res.is_ok());
355 let res = res.unwrap();
356 assert_eq!(res.status(), StatusCode::MOVED_PERMANENTLY);
357 }
358
359 #[test]
362 fn test_response_status() {
363 let res = Response::empty();
364 assert_eq!(res.status(), StatusCode::OK);
365 }
366
367 #[test]
368 fn test_response_set_status() {
369 let mut res = Response::empty();
370 res.set_status(StatusCode::NOT_FOUND);
371 assert_eq!(res.status(), StatusCode::NOT_FOUND);
372 }
373
374 #[test]
375 fn test_response_set_status_multiple() {
376 let mut res = Response::empty();
377 res.set_status(StatusCode::NOT_FOUND);
378 assert_eq!(res.status(), StatusCode::NOT_FOUND);
379 res.set_status(StatusCode::INTERNAL_SERVER_ERROR);
380 assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
381 }
382
383 #[test]
384 fn test_response_with_status() {
385 let res = Response::empty().with_status(StatusCode::CREATED);
386 assert_eq!(res.status(), StatusCode::CREATED);
387 }
388
389 #[test]
390 fn test_response_with_status_chain() {
391 let res = Response::empty()
392 .with_status(StatusCode::CREATED)
393 .with_status(StatusCode::ACCEPTED);
394 assert_eq!(res.status(), StatusCode::ACCEPTED);
395 }
396
397 #[test]
400 fn test_response_body() {
401 let res = Response::text("test");
402 assert!(!res.body().is_end_stream());
403 }
404
405 #[test]
406 fn test_response_set_body() {
407 let mut res = Response::empty();
408 let new_body = full(b"new body".to_vec());
409 res.set_body(new_body);
410 assert!(!res.body().is_end_stream());
411 }
412
413 #[test]
414 fn test_response_with_body() {
415 let body = full(b"test body".to_vec());
416 let res = Response::empty().with_body(body);
417 assert!(!res.body().is_end_stream());
418 }
419
420 #[test]
421 fn test_response_take_body() {
422 let mut res = Response::text("test");
423 let body = res.take_body();
424 assert!(!body.is_end_stream());
425 assert!(res.body().is_end_stream()); }
427
428 #[test]
429 fn test_response_take_body_twice() {
430 let mut res = Response::text("test");
431 let _body1 = res.take_body();
432 let body2 = res.take_body();
433 assert!(body2.is_end_stream());
434 }
435
436 #[test]
437 fn test_response_content_length() {
438 let res = Response::text("Hello, World!");
439 let hint = res.content_length();
440 assert!(hint.lower() > 0);
441 }
442
443 #[test]
444 fn test_response_content_length_empty() {
445 let res = Response::empty();
446 let hint = res.content_length();
447 assert_eq!(hint.lower(), 0);
448 }
449
450 #[test]
453 fn test_response_headers() {
454 let res = Response::text("test");
455 assert!(res.headers().get("content-type").is_some());
456 assert_eq!(res.headers().len(), 1);
457 }
458
459 #[test]
460 fn test_response_headers_empty() {
461 let res = Response::empty();
462 assert_eq!(res.headers().len(), 0);
463 }
464
465 #[test]
466 fn test_response_headers_mut() {
467 let mut res = Response::empty();
468 res.headers_mut()
469 .insert("x-custom-header", "custom-value".parse().unwrap());
470 assert_eq!(res.headers().len(), 1);
471 assert!(res.headers().get("x-custom-header").is_some());
472 }
473
474 #[test]
475 fn test_response_set_header() {
476 let mut res = Response::empty();
477 res.set_header(header::CONTENT_TYPE, "application/json".parse().unwrap());
478 assert!(res.headers().get("content-type").is_some());
479 }
480
481 #[test]
482 fn test_response_set_header_multiple() {
483 let mut res = Response::empty();
484 res.set_header(header::CONTENT_TYPE, "text/plain".parse().unwrap());
485 res.set_header(header::CACHE_CONTROL, "no-cache".parse().unwrap());
486 assert_eq!(res.headers().len(), 2);
487 }
488
489 #[test]
490 fn test_response_with_header() {
491 let res = Response::empty().with_header(header::CONTENT_TYPE, "text/html".parse().unwrap());
492 assert!(res.headers().get("content-type").is_some());
493 }
494
495 #[test]
496 fn test_response_with_header_chain() {
497 let res = Response::empty()
498 .with_header(header::CONTENT_TYPE, "text/plain".parse().unwrap())
499 .with_header(header::CACHE_CONTROL, "no-cache".parse().unwrap());
500 assert_eq!(res.headers().len(), 2);
501 }
502
503 #[test]
504 fn test_response_set_typed_header() {
505 let mut res = Response::empty();
506 res.set_typed_header(ContentType::json());
507 assert!(res.headers().get("content-type").is_some());
508 }
509
510 #[test]
511 fn test_response_with_typed_header() {
512 let res = Response::empty().with_typed_header(ContentType::text_utf8());
513 assert!(res.headers().get("content-type").is_some());
514 }
515
516 #[test]
519 fn test_response_extensions() {
520 let res = Response::empty();
521 assert_eq!(res.extensions().len(), 0);
522 }
523
524 #[test]
525 fn test_response_extensions_mut() {
526 let mut res = Response::empty();
527 res.extensions_mut().insert("test_key");
528 assert_eq!(res.extensions().len(), 1);
529 }
530
531 #[test]
532 fn test_response_extensions_insert_and_get() {
533 let mut res = Response::empty();
534 res.extensions_mut().insert(42i32);
535 assert!(res.extensions().get::<i32>().is_some());
536 }
537
538 #[test]
541 fn test_response_state() {
542 let res = Response::empty();
543 assert_eq!(res.state().len(), 0);
544 }
545
546 #[test]
547 fn test_response_state_mut() {
548 let mut res = Response::empty();
549 res.state_mut().insert(42i32);
550 assert_eq!(res.state().len(), 1);
551 }
552
553 #[test]
554 fn test_response_get_state_not_found() {
555 let res = Response::empty();
556 let result: Result<&i32> = res.get_state();
557 assert!(result.is_err());
558 }
559
560 #[test]
561 fn test_response_get_state_uncheck_panics() {
562 }
567
568 #[test]
569 fn test_response_get_state_success() {
570 let mut res = Response::empty();
571 res.state_mut().insert(42i32);
572 let state: Result<&i32> = res.get_state();
573 assert!(state.is_ok());
574 assert_eq!(*state.unwrap(), 42);
575 }
576
577 #[test]
578 fn test_response_get_state_uncheck_success() {
579 let mut res = Response::empty();
580 res.state_mut().insert(100i32);
581 let state: &i32 = res.get_state_uncheck();
582 assert_eq!(*state, 100);
583 }
584
585 #[test]
588 fn test_response_copy_from_response() {
589 let mut dest = Response::empty();
590 let src = Response::text("source content")
591 .with_status(StatusCode::CREATED)
592 .with_header(header::CACHE_CONTROL, "no-cache".parse().unwrap());
593
594 dest.copy_from_response(src);
595 assert_eq!(dest.status(), StatusCode::CREATED);
596 assert!(dest.headers().get("cache-control").is_some());
597 assert!(!dest.body().is_end_stream());
598 }
599
600 #[test]
601 fn test_response_copy_from_response_preserves_some_headers() {
602 let mut dest =
603 Response::empty().with_header(header::CONTENT_TYPE, "text/plain".parse().unwrap());
604 let src = Response::html("<html>source</html>");
605
606 dest.copy_from_response(src);
607 assert!(dest.headers().get("content-type").is_some());
609 }
610
611 #[test]
612 fn test_response_copy_from_response_empty_source() {
613 let mut dest = Response::text("destination");
614 let src = Response::empty();
615
616 dest.copy_from_response(src);
617 assert_eq!(dest.status(), StatusCode::OK);
618 }
619
620 #[test]
623 fn test_response_from_string() {
624 let res: Response = "test string".to_string().into();
625 assert_eq!(res.status(), StatusCode::OK);
626 assert!(res.headers().get("content-type").is_some());
627 }
628
629 #[test]
630 fn test_response_from_integer() {
631 let res: Response = 42.into();
632 assert_eq!(res.status(), StatusCode::OK);
633 assert!(res.headers().get("content-type").is_some());
634 }
635
636 #[test]
637 fn test_response_from_struct() {
638 #[derive(Serialize)]
639 struct TestData {
640 field: String,
641 }
642 let data = TestData {
643 field: "value".to_string(),
644 };
645 let res: Response = data.into();
646 assert_eq!(res.status(), StatusCode::OK);
647 }
648
649 #[test]
650 fn test_response_from_null_value() {
651 let value: Option<i32> = None;
652 let res: Response = value.into();
653 assert_eq!(res.status(), StatusCode::NO_CONTENT);
654 }
655
656 #[test]
657 fn test_response_from_json_object() {
658 #[derive(Serialize)]
659 struct Person {
660 name: String,
661 age: i32,
662 }
663 let person = Person {
664 name: "Alice".to_string(),
665 age: 30,
666 };
667 let res: Response = person.into();
668 assert_eq!(res.status(), StatusCode::OK);
669 }
670
671 #[test]
674 fn test_response_debug_format() {
675 let res = Response::text("test");
676 let debug_str = format!("{:?}", res);
677 assert!(debug_str.contains("HTTP"));
678 assert!(debug_str.contains("200 OK"));
679 }
680
681 #[test]
682 fn test_response_display_format() {
683 let res = Response::text("test");
684 let display_str = format!("{}", res);
685 assert!(!display_str.is_empty());
686 }
687
688 #[test]
689 fn test_response_display_equals_debug() {
690 let res = Response::empty();
691 let debug_str = format!("{:?}", res);
692 let display_str = format!("{}", res);
693 assert_eq!(debug_str, display_str);
695 }
696
697 #[test]
700 fn test_response_empty_text() {
701 let res = Response::text("");
702 assert_eq!(res.status(), StatusCode::OK);
703 assert!(res.headers().get("content-type").is_some());
704 }
705
706 #[test]
707 fn test_response_empty_html() {
708 let res = Response::html("");
709 assert_eq!(res.status(), StatusCode::OK);
710 assert!(res.headers().get("content-type").is_some());
711 }
712
713 #[test]
714 fn test_response_empty_json() {
715 let data: serde_json::Value = serde_json::json!({});
716 let res = Response::json(&data);
717 assert_eq!(res.status(), StatusCode::OK);
718 }
719
720 #[test]
721 fn test_response_unicode_text() {
722 let text = "你好,世界!🌍";
723 let res = Response::text(text);
724 assert_eq!(res.status(), StatusCode::OK);
725 }
726
727 #[test]
728 fn test_response_large_body() {
729 let large_text = "x".repeat(1000000);
730 let res = Response::text(&large_text);
731 let hint = res.content_length();
732 assert!(hint.lower() >= 1000000);
733 }
734
735 #[test]
736 fn test_response_set_body_after_take() {
737 let mut res = Response::text("original");
738 let _ = res.take_body();
739 res.set_body(full(b"new body".to_vec()));
740 assert!(!res.body().is_end_stream());
741 }
742
743 #[test]
744 fn test_response_status_code_range() {
745 let mut res = Response::empty();
746 for code in [100, 200, 301, 404, 500] {
747 res.set_status(StatusCode::from_u16(code).unwrap());
748 assert_eq!(res.status().as_u16(), code);
749 }
750 }
751
752 #[test]
753 fn test_response_version_default() {
754 let res = Response::empty();
755 assert_eq!(res.version, Version::default());
756 }
757
758 #[test]
759 fn test_response_multiple_headers_same_name() {
760 let mut res = Response::empty();
761 res.headers_mut()
762 .append("x-custom", "value1".parse().unwrap());
763 res.headers_mut()
764 .append("x-custom", "value2".parse().unwrap());
765 let values: Vec<_> = res.headers().get_all("x-custom").iter().collect();
766 assert_eq!(values.len(), 2);
767 }
768}