http_kit/
response.rs

1//! HTTP response implementation.
2//!
3//! This module provides the [`Response`] type which represents an HTTP response including
4//! headers, status code, version, and body. It offers comprehensive methods for:
5//!
6//! - **Response creation** - Building responses with different status codes and body types
7//! - **Header manipulation** - Setting, getting, and modifying HTTP headers
8//! - **Body handling** - Working with various body formats (bytes, strings, JSON, form data, files)
9//! - **Extensions** - Storing custom application data associated with the response
10//! - **Content types** - Automatic MIME type detection and content type headers
11//!
12//! The [`Response`] type integrates seamlessly with the body system and provides convenient
13//! conversions from common Rust types like `String`, `Vec<u8>`, `Bytes`, etc.
14//!
15//! # Examples
16//!
17//! ## Basic Response Creation
18//!
19//! ```rust
20//! use http_kit::{Response, StatusCode};
21//!
22//! // Simple text response
23//! let response = Response::new(StatusCode::OK, "Hello, World!");
24//!
25//! // Empty response
26//! let empty = Response::empty();
27//!
28//! // Response with custom status
29//! let not_found = Response::new(404, "Page not found");
30//! ```
31//!
32//! ## Working with Headers
33//!
34//! ```rust
35//! use http_kit::Response;
36//!
37//! let response = Response::new(200, "OK")
38//!     .header(http::header::CONTENT_TYPE, "text/plain")
39//!     .header(http::header::SERVER, "http-kit/1.0");
40//! ```
41//!
42//! ## JSON Responses
43//!
44//! ```rust
45//! # #[cfg(feature = "json")]
46//! # {
47//! use http_kit::Response;
48//! use serde::Serialize;
49//!
50//! #[derive(Serialize)]
51//! struct User { name: String, id: u32 }
52//!
53//! let user = User { name: "Alice".to_string(), id: 123 };
54//! let response = Response::empty().json(&user)?;
55//! # }
56//! # Ok::<(), serde_json::Error>(())
57//! ```
58//!
59//! ## File Responses
60//!
61//! ```rust,no_run
62//! # #[cfg(feature = "fs")]
63//! # {
64//! use http_kit::Response;
65//!
66//! # async fn example() -> Result<(), std::io::Error> {
67//! let response = Response::empty().file("static/index.html").await?;
68//! // Content-Type header will be set automatically based on file extension
69//! # Ok(())
70//! # }
71//! # }
72//! ```
73use core::fmt::Debug;
74
75use crate::{body::BodyFrozen, Body, BodyError};
76use alloc::string::String;
77use alloc::vec::Vec;
78use bytes::Bytes;
79use bytestr::ByteStr;
80use http::{
81    header::{GetAll, HeaderName},
82    Extensions, HeaderMap, HeaderValue, StatusCode, Version,
83};
84
85/// The HTTP response parts.
86pub type ResponseParts = http::response::Parts;
87
88/// An HTTP response with status, headers, and body.
89///
90/// `Response` represents a complete HTTP response that can be constructed, modified,
91/// and sent back to clients. It provides comprehensive methods for working with all
92/// aspects of HTTP responses including:
93///
94/// - **Status codes** - Setting and querying HTTP status codes (200, 404, 500, etc.)
95/// - **Headers** - Managing HTTP headers for metadata, caching, content type, etc.
96/// - **Body content** - Handling response payloads in various formats
97/// - **HTTP version** - Specifying the HTTP protocol version
98/// - **Extensions** - Storing custom application data
99///
100/// The response type integrates with the body system to provide convenient methods
101/// for handling different content types like JSON, form data, files, and raw bytes.
102///
103/// # Examples
104///
105/// ## Creating Basic Responses
106///
107/// ```rust
108/// use http_kit::{Response, StatusCode};
109///
110/// // Success response with text
111/// let ok = Response::new(200, "Operation successful");
112///
113/// // Error response
114/// let error = Response::new(StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong");
115///
116/// // Empty response
117/// let empty = Response::empty();
118/// ```
119///
120/// ## Building Rich Responses
121///
122/// ```rust
123/// use http_kit::Response;
124///
125/// let response = Response::new(201, "Created")
126///     .header(http::header::LOCATION, "/api/users/123")
127///     .header(http::header::CONTENT_TYPE, "text/plain");
128/// ```
129///
130/// ## Working with Body Content
131///
132/// ```rust
133/// # async fn example() -> Result<(), http_kit::BodyError> {
134/// use http_kit::Response;
135///
136/// let mut response = Response::new(200, "Hello, world!");
137///
138/// // Read the body content
139/// let content = response.into_string().await?;
140/// assert_eq!(content, "Hello, world!");
141/// # Ok(())
142/// # }
143/// ```
144#[derive(Debug)]
145pub struct Response {
146    parts: ResponseParts,
147    body: Body,
148}
149
150impl From<http::Response<Body>> for Response {
151    fn from(response: http::Response<Body>) -> Self {
152        let (parts, body) = response.into_parts();
153        Self { parts, body }
154    }
155}
156
157impl From<Response> for http::Response<Body> {
158    fn from(response: Response) -> Self {
159        Self::from_parts(response.parts, response.body)
160    }
161}
162
163macro_rules! impl_response_from {
164    ($($ty:ty),*) => {
165        $(
166            impl From<$ty> for Response {
167                fn from(value: $ty) -> Self {
168                    Self::new(StatusCode::OK, value)
169                }
170            }
171        )*
172    };
173}
174
175impl_response_from![ByteStr, String, Vec<u8>, Bytes, &str, &[u8]];
176
177impl Response {
178    /// Creates a new HTTP response with the specified status code and body.
179    ///
180    /// This is the primary constructor for building responses. The body can be any type
181    /// that converts to `Body`, including strings, byte vectors, and `Bytes` objects.
182    ///
183    /// # Arguments
184    ///
185    /// * `status` - The HTTP status code (or value convertible to `StatusCode`)
186    /// * `body` - The response body (any type convertible to `Body`)
187    ///
188    /// # Examples
189    ///
190    /// ```rust
191    /// use http_kit::{Response, StatusCode};
192    ///
193    /// // With numeric status code
194    /// let response = Response::new(200, "Success");
195    ///
196    /// // With StatusCode enum
197    /// let response = Response::new(StatusCode::CREATED, "Resource created");
198    ///
199    /// // With byte vector
200    /// let response = Response::new(200, vec![72, 101, 108, 108, 111]);
201    ///
202    /// // With string
203    /// let response = Response::new(200, "Hello, world!".to_string());
204    /// ```
205    pub fn new<S>(status: S, body: impl Into<Body>) -> Self
206    where
207        S: TryInto<StatusCode>,
208        S::Error: Debug,
209    {
210        let mut response: Self = http::Response::new(body.into()).into();
211        response.set_status(status.try_into().unwrap());
212        response
213    }
214
215    /// Creates an empty HTTP response with status 200 OK.
216    ///
217    /// This is a convenience method for creating responses that don't need body content,
218    /// such as successful operations that only need to indicate completion.
219    ///
220    /// # Examples
221    ///
222    /// ```rust
223    /// use http_kit::Response;
224    ///
225    /// let response = Response::empty();
226    /// assert_eq!(response.status(), http::StatusCode::OK);
227    /// ```
228    pub fn empty() -> Self {
229        Self::new(StatusCode::OK, Body::empty())
230    }
231
232    /// Returns the HTTP status code of this response.
233    ///
234    /// # Examples
235    ///
236    /// ```rust
237    /// use http_kit::{Response, StatusCode};
238    ///
239    /// let response = Response::new(404, "Not found");
240    /// assert_eq!(response.status(), StatusCode::NOT_FOUND);
241    /// ```
242    pub const fn status(&self) -> StatusCode {
243        self.parts.status
244    }
245    /// Returns a mutable reference to the HTTP status code.
246    ///
247    /// This allows direct modification of the status code.
248    ///
249    /// # Examples
250    ///
251    /// ```rust
252    /// use http_kit::{Response, StatusCode};
253    ///
254    /// let mut response = Response::empty();
255    /// *response.status_mut() = StatusCode::CREATED;
256    /// assert_eq!(response.status(), StatusCode::CREATED);
257    /// ```
258    pub fn status_mut(&mut self) -> &mut StatusCode {
259        &mut self.parts.status
260    }
261
262    /// Sets the HTTP status code for this response.
263    ///
264    /// # Arguments
265    ///
266    /// * `status` - The new status code
267    ///
268    /// # Examples
269    ///
270    /// ```rust
271    /// use http_kit::{Response, StatusCode};
272    ///
273    /// let mut response = Response::empty();
274    /// response.set_status(StatusCode::NOT_FOUND);
275    /// assert_eq!(response.status(), StatusCode::NOT_FOUND);
276    /// ```
277    pub fn set_status(&mut self, status: StatusCode) {
278        *self.status_mut() = status;
279    }
280
281    /// Returns the HTTP version for this response.
282    ///
283    /// # Examples
284    ///
285    /// ```rust
286    /// use http_kit::{Response, Version};
287    ///
288    /// let response = Response::empty();
289    /// // Default version is typically HTTP/1.1
290    /// assert_eq!(response.version(), Version::HTTP_11);
291    /// ```
292    pub const fn version(&self) -> Version {
293        self.parts.version
294    }
295
296    /// Returns a mutable reference to the HTTP version.
297    ///
298    /// This allows direct modification of the HTTP version.
299    ///
300    /// # Examples
301    ///
302    /// ```rust
303    /// use http_kit::{Response, Version};
304    ///
305    /// let mut response = Response::empty();
306    /// *response.version_mut() = Version::HTTP_2;
307    /// assert_eq!(response.version(), Version::HTTP_2);
308    /// ```
309    pub fn version_mut(&mut self) -> &mut Version {
310        &mut self.parts.version
311    }
312
313    /// Sets the HTTP version for this response.
314    ///
315    /// # Arguments
316    ///
317    /// * `version` - The HTTP version to use
318    ///
319    /// # Examples
320    ///
321    /// ```rust
322    /// use http_kit::{Response, Version};
323    ///
324    /// let mut response = Response::empty();
325    /// response.set_version(Version::HTTP_2);
326    /// assert_eq!(response.version(), Version::HTTP_2);
327    /// ```
328    pub fn set_version(&mut self, version: Version) {
329        *self.version_mut() = version;
330    }
331
332    /// Returns a reference to the HTTP headers.
333    ///
334    /// # Examples
335    ///
336    /// ```rust
337    /// use http_kit::Response;
338    ///
339    /// let response = Response::new(200, "OK")
340    ///     .header(http::header::CONTENT_TYPE, "text/plain");
341    ///
342    /// let headers = response.headers();
343    /// assert!(headers.contains_key(http::header::CONTENT_TYPE));
344    /// ```
345    pub const fn headers(&self) -> &HeaderMap {
346        &self.parts.headers
347    }
348
349    /// Returns a mutable reference to the HTTP headers.
350    ///
351    /// This allows direct manipulation of the header map.
352    ///
353    /// # Examples
354    ///
355    /// ```rust
356    /// use http_kit::Response;
357    ///
358    /// let mut response = Response::empty();
359    /// response.headers_mut().insert(
360    ///     http::header::CONTENT_TYPE,
361    ///     "application/json".parse().unwrap()
362    /// );
363    /// ```
364    pub fn headers_mut(&mut self) -> &mut HeaderMap {
365        &mut self.parts.headers
366    }
367
368    /// Returns the first value for the given header name.
369    ///
370    /// If the header has multiple values, only the first one is returned.
371    /// Returns `None` if the header is not present.
372    ///
373    /// # Arguments
374    ///
375    /// * `name` - The header name to look up
376    ///
377    /// # Examples
378    ///
379    /// ```rust
380    /// use http_kit::Response;
381    ///
382    /// let response = Response::new(200, "OK")
383    ///     .header(http::header::CONTENT_TYPE, "application/json");
384    ///
385    /// if let Some(content_type) = response.get_header(http::header::CONTENT_TYPE) {
386    ///     assert_eq!(content_type, "application/json");
387    /// }
388    /// ```
389    pub fn get_header(&self, name: HeaderName) -> Option<&HeaderValue> {
390        self.headers().get(name)
391    }
392
393    /// Returns an iterator over all values for a given header name.
394    ///
395    /// This method retrieves all values associated with a header name, since
396    /// HTTP headers can have multiple values. The returned iterator will yield
397    /// each value in the order they were added.
398    ///
399    /// # Arguments
400    ///
401    /// * `name` - The header name to get values for
402    ///
403    /// # Examples
404    ///
405    /// ```rust
406    /// use http_kit::Response;
407    ///
408    /// let response = Response::new(200, "OK")
409    ///     .header(http::header::SET_COOKIE, "session=123")
410    ///     .header(http::header::SET_COOKIE, "theme=dark");
411    ///
412    /// for cookie in response.get_headers(http::header::SET_COOKIE) {
413    ///     // Iterate over each Set-Cookie header value
414    /// }
415    /// ```
416    pub fn get_headers(&self, name: HeaderName) -> GetAll<'_, HeaderValue> {
417        self.headers().get_all(name)
418    }
419
420    /// Appends a header value without removing existing values.
421    ///
422    /// If a header with the same name already exists, the new value is added
423    /// alongside the existing values rather than replacing them.
424    ///
425    /// # Arguments
426    ///
427    /// * `name` - The header name
428    /// * `value` - The header value to append
429    ///
430    /// # Examples
431    ///
432    /// ```rust
433    /// use http_kit::Response;
434    ///
435    /// let mut response = Response::empty();
436    /// response.append_header(http::header::SET_COOKIE, "session=abc123".parse().unwrap());
437    /// response.append_header(http::header::SET_COOKIE, "theme=dark".parse().unwrap());
438    /// // Both cookies will be present in the response
439    /// ```
440    pub fn append_header(&mut self, name: HeaderName, value: HeaderValue) {
441        self.headers_mut().append(name, value);
442    }
443
444    /// Inserts a header value, replacing any existing values.
445    ///
446    /// If a header with the same name already exists, it is completely replaced
447    /// with the new value.
448    ///
449    /// # Arguments
450    ///
451    /// * `name` - The header name
452    /// * `value` - The header value
453    ///
454    /// # Returns
455    ///
456    /// Returns the previous header value if one existed.
457    ///
458    /// # Examples
459    ///
460    /// ```rust
461    /// use http_kit::Response;
462    ///
463    /// let mut response = Response::empty();
464    /// let old_value = response.insert_header(
465    ///     http::header::SERVER,
466    ///     "http-kit/1.0".parse().unwrap()
467    /// );
468    /// assert!(old_value.is_none());
469    ///
470    /// let old_value = response.insert_header(
471    ///     http::header::SERVER,
472    ///     "http-kit/2.0".parse().unwrap()
473    /// );
474    /// assert!(old_value.is_some());
475    /// ```
476    pub fn insert_header(&mut self, name: HeaderName, value: HeaderValue) -> Option<HeaderValue> {
477        self.headers_mut().insert(name, value)
478    }
479
480    /// Sets an HTTP header and returns the modified response.
481    ///
482    /// This is a builder-style method that allows method chaining. If you need to
483    /// modify an existing response, use [`insert_header`] instead.
484    ///
485    /// # Arguments
486    ///
487    /// * `name` - The header name
488    /// * `value` - The header value
489    ///
490    /// # Examples
491    ///
492    /// ```rust
493    /// use http_kit::Response;
494    ///
495    /// let response = Response::new(200, "OK")
496    ///     .header(http::header::CONTENT_TYPE, "application/json")
497    ///     .header(http::header::SERVER, "http-kit/1.0");
498    /// ```
499    ///
500    /// [`insert_header`]: Response::insert_header
501    pub fn header<V>(mut self, name: HeaderName, value: V) -> Self
502    where
503        V: TryInto<HeaderValue>,
504        V::Error: Debug,
505    {
506        self.insert_header(name, value.try_into().unwrap());
507        self
508    }
509
510    /// Returns a reference to the response extensions.
511    ///
512    /// Extensions provide a type-safe way to store additional data associated
513    /// with the response that doesn't fit into standard HTTP fields.
514    ///
515    /// # Examples
516    ///
517    /// ```rust
518    /// use http_kit::Response;
519    ///
520    /// let response = Response::empty();
521    /// let extensions = response.extensions();
522    /// // Check if a specific type is stored
523    /// let timing: Option<&u64> = extensions.get();
524    /// ```
525    pub const fn extensions(&self) -> &Extensions {
526        &self.parts.extensions
527    }
528
529    /// Returns a mutable reference to the response extensions.
530    ///
531    /// This allows modification of the extensions map.
532    ///
533    /// # Examples
534    ///
535    /// ```rust
536    /// use http_kit::Response;
537    ///
538    /// let mut response = Response::empty();
539    /// response.extensions_mut().insert(42u32);
540    /// ```
541    pub fn extensions_mut(&mut self) -> &mut Extensions {
542        &mut self.parts.extensions
543    }
544
545    /// Returns a reference to an extension of the specified type.
546    ///
547    /// # Type Parameters
548    ///
549    /// * `T` - The type to retrieve from extensions
550    ///
551    /// # Examples
552    ///
553    /// ```rust
554    /// use http_kit::Response;
555    ///
556    /// let mut response = Response::empty();
557    /// response.insert_extension(42u32);
558    ///
559    /// if let Some(value) = response.get_extension::<u32>() {
560    ///     assert_eq!(*value, 42);
561    /// }
562    /// ```
563    pub fn get_extension<T: Send + Sync + 'static>(&self) -> Option<&T> {
564        self.extensions().get()
565    }
566
567    /// Returns a mutable reference to an extension of the specified type.
568    ///
569    /// # Type Parameters
570    ///
571    /// * `T` - The type to retrieve from extensions
572    ///
573    /// # Examples
574    ///
575    /// ```rust
576    /// use http_kit::Response;
577    ///
578    /// let mut response = Response::empty();
579    /// response.insert_extension(42u32);
580    ///
581    /// if let Some(value) = response.get_mut_extension::<u32>() {
582    ///     *value = 100;
583    /// }
584    /// ```
585    pub fn get_mut_extension<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
586        self.extensions_mut().get_mut()
587    }
588
589    /// Removes and returns an extension of the specified type.
590    ///
591    /// # Type Parameters
592    ///
593    /// * `T` - The type to remove from extensions
594    ///
595    /// # Returns
596    ///
597    /// Returns the removed value if it existed, or `None` if it wasn't present.
598    ///
599    /// # Examples
600    ///
601    /// ```rust
602    /// use http_kit::Response;
603    ///
604    /// let mut response = Response::empty();
605    /// response.insert_extension(42u32);
606    ///
607    /// let removed = response.remove_extension::<u32>();
608    /// assert_eq!(removed, Some(42));
609    ///
610    /// let removed_again = response.remove_extension::<u32>();
611    /// assert_eq!(removed_again, None);
612    /// ```
613    pub fn remove_extension<T: Send + Sync + 'static>(&mut self) -> Option<T> {
614        self.extensions_mut().remove()
615    }
616
617    /// Inserts an extension value, returning any previous value of the same type.
618    ///
619    /// # Type Parameters
620    ///
621    /// * `T` - The type to insert into extensions
622    ///
623    /// # Arguments
624    ///
625    /// * `extension` - The value to insert
626    ///
627    /// # Returns
628    ///
629    /// Returns the previous value of the same type if one existed.
630    ///
631    /// # Examples
632    ///
633    /// ```rust
634    /// use http_kit::Response;
635    ///
636    /// let mut response = Response::empty();
637    ///
638    /// let old_value = response.insert_extension(42u32);
639    /// assert_eq!(old_value, None);
640    ///
641    /// let old_value = response.insert_extension(100u32);
642    /// assert_eq!(old_value, Some(42));
643    /// ```
644    pub fn insert_extension<T: Send + Sync + Clone + 'static>(
645        &mut self,
646        extension: T,
647    ) -> Option<T> {
648        self.extensions_mut().insert(extension)
649    }
650
651    /// Takes the response body, leaving a frozen (unusable) body in its place.
652    ///
653    /// This method extracts the body from the response while ensuring it cannot
654    /// be accessed again. This is useful when you need to consume the body
655    /// for processing while preventing accidental double-consumption.
656    ///
657    /// # Errors
658    ///
659    /// Returns `BodyFrozen` if the body has already been taken.
660    ///
661    /// # Examples
662    ///
663    /// ```rust
664    /// use http_kit::Response;
665    ///
666    /// let mut response = Response::new(200, "Hello, world!");
667    /// let body = response.take_body()?;
668    /// // response.take_body() would now return an error
669    /// # Ok::<(), http_kit::BodyError>(())
670    /// ```
671    pub fn take_body(&mut self) -> Result<Body, BodyFrozen> {
672        self.body.take()
673    }
674
675    /// Replaces the response body and returns the previous body.
676    ///
677    /// This method swaps the current body with a new one, returning the
678    /// original body. This is useful for body transformations or when
679    /// you need to temporarily substitute the body content.
680    ///
681    /// # Arguments
682    ///
683    /// * `body` - The new body to set (anything convertible to `Body`)
684    ///
685    /// # Examples
686    ///
687    /// ```rust
688    /// use http_kit::Response;
689    ///
690    /// let mut response = Response::new(200, "Original content");
691    /// let old_body = response.replace_body("New content");
692    /// // old_body contains "Original content"
693    /// // response now contains "New content"
694    /// ```
695    pub fn replace_body(&mut self, body: impl Into<Body>) -> Body {
696        self.body.replace(body.into())
697    }
698
699    /// Swaps the response body with another body.
700    ///
701    /// This method exchanges the contents of the response body with another body,
702    /// provided that the response body is not frozen.
703    ///
704    /// # Arguments
705    ///
706    /// * `body` - The body to swap with
707    ///
708    /// # Errors
709    ///
710    /// Returns `BodyFrozen` if the response body has been frozen/consumed.
711    ///
712    /// # Examples
713    ///
714    /// ```rust
715    /// use http_kit::{Response, Body};
716    ///
717    /// let mut response = Response::new(200, "Response content");
718    /// let mut other_body = Body::from_bytes("Other content");
719    /// response.swap_body(&mut other_body)?;
720    ///
721    /// // Now response contains "Other content"
722    /// // and other_body contains "Response content"
723    /// # Ok::<(), http_kit::BodyError>(())
724    /// ```
725    pub fn swap_body(&mut self, body: &mut Body) -> Result<(), BodyFrozen> {
726        self.body.swap(body)
727    }
728
729    /// Transforms the response body using the provided function.
730    ///
731    /// This method allows you to apply a transformation to the response body
732    /// in a functional style, returning a new response with the transformed body.
733    ///
734    /// # Arguments
735    ///
736    /// * `f` - A function that takes the current body and returns a new body
737    ///
738    /// # Examples
739    ///
740    /// ```rust
741    /// use http_kit::{Response, Body};
742    ///
743    /// let response = Response::new(200, "original")
744    ///     .map_body(|body| {
745    ///         // Transform body to uppercase JSON
746    ///         Body::from_bytes(r#"{"message": "ORIGINAL"}"#)
747    ///     });
748    /// ```
749    pub fn map_body<F>(mut self, f: F) -> Self
750    where
751        F: FnOnce(Body) -> Body,
752    {
753        self.body = f(self.body);
754        self
755    }
756
757    /// Sets the body from a JSON-serializable value.
758    ///
759    /// This method serializes the provided value to JSON and sets it as the response body.
760    /// It also automatically sets the `Content-Type` header to `application/json`.
761    ///
762    /// # Arguments
763    ///
764    /// * `value` - Any value that implements `serde::Serialize`
765    ///
766    /// # Errors
767    ///
768    /// Returns `serde_json::Error` if JSON serialization fails.
769    ///
770    /// # Examples
771    ///
772    /// ```rust
773    /// # #[cfg(feature = "json")]
774    /// # {
775    /// use http_kit::Response;
776    /// use serde::Serialize;
777    ///
778    /// #[derive(Serialize)]
779    /// struct ApiResponse { success: bool, message: String }
780    ///
781    /// let data = ApiResponse {
782    ///     success: true,
783    ///     message: "Operation completed".to_string(),
784    /// };
785    ///
786    /// let response = Response::empty().json(&data)?;
787    /// # }
788    /// # Ok::<(), serde_json::Error>(())
789    /// ```
790    #[cfg(feature = "json")]
791    pub fn json<T: serde::Serialize>(mut self, value: &T) -> Result<Self, serde_json::Error> {
792        use http::header;
793
794        self.insert_header(
795            header::CONTENT_TYPE,
796            HeaderValue::from_static("application/json"),
797        );
798        self.replace_body(Body::from_json(value)?);
799        Ok(self)
800    }
801
802    /// Sets the body from a file, streaming its contents.
803    ///
804    /// This method opens the specified file and streams its contents as the response body.
805    /// It automatically detects the MIME type based on the file extension and sets the
806    /// appropriate `Content-Type` header.
807    ///
808    /// # Arguments
809    ///
810    /// * `path` - Path to the file to read
811    ///
812    /// # Errors
813    ///
814    /// Returns `io::Error` if the file cannot be opened or read.
815    ///
816    /// # Examples
817    ///
818    /// ```rust,no_run
819    /// # #[cfg(feature = "fs")]
820    /// # {
821    /// use http_kit::Response;
822    ///
823    /// # async fn example() -> Result<(), std::io::Error> {
824    /// let response = Response::empty().file("static/logo.png").await?;
825    /// // Content-Type will be automatically set to "image/png"
826    /// # Ok(())
827    /// # }
828    /// # }
829    /// ```
830    #[cfg(feature = "fs")]
831    pub async fn file(
832        mut self,
833        path: impl AsRef<core::path::Path>,
834    ) -> Result<Self, core::io::Error> {
835        use core::os::unix::ffi::OsStrExt;
836
837        let path = path.as_ref();
838        let extension = path.extension().unwrap_or_default().as_bytes();
839        let mime = crate::mime_guess::guess(extension).unwrap_or("application/octet-stream");
840        self.replace_body(Body::from_file(path).await?);
841        self.insert_header(http::header::CONTENT_TYPE, HeaderValue::from_static(mime));
842        Ok(self)
843    }
844
845    /// Sets the body from a form-serializable value.
846    ///
847    /// This method serializes the provided value to URL-encoded form data and sets it
848    /// as the response body. It also automatically sets the `Content-Type` header to
849    /// `application/x-www-form-urlencoded`.
850    ///
851    /// # Arguments
852    ///
853    /// * `value` - Any value that implements `serde::Serialize`
854    ///
855    /// # Errors
856    ///
857    /// Returns `serde_urlencoded::ser::Error` if form serialization fails.
858    ///
859    /// # Examples
860    ///
861    /// ```rust
862    /// # #[cfg(feature = "form")]
863    /// # {
864    /// use http_kit::Response;
865    /// use serde::Serialize;
866    ///
867    /// #[derive(Serialize)]
868    /// struct FormData { key: String, value: String }
869    ///
870    /// let data = FormData {
871    ///     key: "name".to_string(),
872    ///     value: "Alice".to_string(),
873    /// };
874    ///
875    /// let response = Response::empty().form(&data)?;
876    /// # }
877    /// # Ok::<(), serde_urlencoded::ser::Error>(())
878    /// ```
879    #[cfg(feature = "form")]
880    pub fn form<T: serde::Serialize>(
881        mut self,
882        value: &T,
883    ) -> Result<Self, serde_urlencoded::ser::Error> {
884        use http::header;
885
886        self.insert_header(
887            header::CONTENT_TYPE,
888            HeaderValue::from_static("application/x-www-form-urlencoded"),
889        );
890        self.replace_body(Body::from_form(value)?);
891        Ok(self)
892    }
893
894    /// Consumes the response body and returns its data as bytes.
895    ///
896    /// This method takes the response body and reads all its data into memory,
897    /// returning it as a `Bytes` object. The body becomes unavailable after this call.
898    ///
899    /// # Errors
900    ///
901    /// Returns `BodyError` if:
902    /// - The body has already been consumed
903    /// - An I/O error occurs while reading streaming data
904    ///
905    /// # Examples
906    ///
907    /// ```rust
908    /// use http_kit::Response;
909    ///
910    /// # async fn example() -> Result<(), http_kit::BodyError> {
911    /// let mut response = Response::new(200, "Hello, world!");
912    /// let bytes = response.into_bytes().await?;
913    /// assert_eq!(bytes, "Hello, world!");
914    /// # Ok(())
915    /// # }
916    /// ```
917    pub async fn into_bytes(&mut self) -> Result<Bytes, BodyError> {
918        self.take_body()?.into_bytes().await
919    }
920
921    /// Consumes the response body and returns its data as a UTF-8 string.
922    ///
923    /// This method takes the response body, reads all its data into memory,
924    /// and converts it to a UTF-8 string. The body becomes unavailable after this call.
925    ///
926    /// # Errors
927    ///
928    /// Returns `BodyError` if:
929    /// - The body has already been consumed
930    /// - An I/O error occurs while reading streaming data
931    /// - The body contains invalid UTF-8 sequences
932    ///
933    /// # Examples
934    ///
935    /// ```rust
936    /// use http_kit::Response;
937    ///
938    /// # async fn example() -> Result<(), http_kit::BodyError> {
939    /// let mut response = Response::new(200, "Hello, world!");
940    /// let text = response.into_string().await?;
941    /// assert_eq!(text, "Hello, world!");
942    /// # Ok(())
943    /// # }
944    /// ```
945    pub async fn into_string(&mut self) -> Result<ByteStr, BodyError> {
946        self.take_body()?.into_string().await
947    }
948
949    /// Deserializes the response body as JSON into the specified type.
950    ///
951    /// This method reads the response body and attempts to deserialize it as JSON.
952    /// It validates that the `Content-Type` header is `application/json` before
953    /// attempting deserialization, making it safe for API clients.
954    ///
955    /// The deserialization is performed with zero-copy when possible by working
956    /// directly with the buffered byte data.
957    ///
958    /// # Errors
959    ///
960    /// Returns `crate::Error` if:
961    /// - The `Content-Type` header is not `application/json`
962    /// - The body has already been consumed
963    /// - The JSON is malformed or doesn't match the target type
964    ///
965    /// # Examples
966    ///
967    /// ```rust
968    /// # #[cfg(feature = "json")]
969    /// # {
970    /// use http_kit::Response;
971    /// use serde::Deserialize;
972    ///
973    /// #[derive(Deserialize)]
974    /// struct ApiResponse { success: bool, message: String }
975    ///
976    /// # async fn example() -> Result<(), http_kit::Error> {
977    /// let json_data = r#"{"success": true, "message": "OK"}"#;
978    /// let mut response = Response::new(200, json_data)
979    ///     .header(http::header::CONTENT_TYPE, "application/json");
980    ///
981    /// let data: ApiResponse = response.into_json().await?;
982    /// assert!(data.success);
983    /// # Ok(())
984    /// # }
985    /// # }
986    /// ```
987    #[cfg(feature = "json")]
988    pub async fn into_json<'a, T>(&'a mut self) -> Result<T, crate::Error>
989    where
990        T: serde::Deserialize<'a>,
991    {
992        use crate::ResultExt;
993
994        assert_content_type!("application/json", self.headers());
995        serde_json::from_slice(self.body.as_bytes().await?).status(crate::StatusCode::BAD_REQUEST)
996    }
997
998    /// Deserializes the response body as URL-encoded form data into the specified type.
999    ///
1000    /// This method reads the response body and attempts to deserialize it as
1001    /// `application/x-www-form-urlencoded` data. It validates that the `Content-Type`
1002    /// header matches before attempting deserialization.
1003    ///
1004    /// The deserialization is performed with zero-copy when possible by working
1005    /// directly with the buffered byte data.
1006    ///
1007    /// # Errors
1008    ///
1009    /// Returns `crate::Error` if:
1010    /// - The `Content-Type` header is not `application/x-www-form-urlencoded`
1011    /// - The body has already been consumed
1012    /// - The form data is malformed or doesn't match the target type
1013    ///
1014    /// # Examples
1015    ///
1016    /// ```rust
1017    /// # #[cfg(feature = "form")]
1018    /// # {
1019    /// use http_kit::Response;
1020    /// use serde::Deserialize;
1021    ///
1022    /// #[derive(Deserialize)]
1023    /// struct FormResponse { status: String, code: u32 }
1024    ///
1025    /// # async fn example() -> Result<(), http_kit::Error> {
1026    /// let form_data = "status=success&code=200";
1027    /// let mut response = Response::new(200, form_data)
1028    ///     .header(http::header::CONTENT_TYPE, "application/x-www-form-urlencoded");
1029    ///
1030    /// let data: FormResponse = response.into_form().await?;
1031    /// assert_eq!(data.status, "success");
1032    /// # Ok(())
1033    /// # }
1034    /// # }
1035    /// ```
1036    #[cfg(feature = "form")]
1037    pub async fn into_form<'a, T>(&'a mut self) -> Result<T, crate::Error>
1038    where
1039        T: serde::Deserialize<'a>,
1040    {
1041        use crate::ResultExt;
1042
1043        assert_content_type!("application/x-www-form-urlencoded", self.headers());
1044        serde_urlencoded::from_bytes(self.body.as_bytes().await?)
1045            .status(crate::StatusCode::BAD_REQUEST)
1046    }
1047
1048    /// Sets the MIME type for the response.
1049    ///
1050    /// This method sets the `Content-Type` header using a parsed MIME type,
1051    /// providing type safety and validation for content types.
1052    ///
1053    /// # Arguments
1054    ///
1055    /// * `mime` - The MIME type to set
1056    ///
1057    /// # Examples
1058    ///
1059    /// ```rust
1060    /// # #[cfg(feature = "mime")]
1061    /// # {
1062    /// use http_kit::Response;
1063    /// use mime;
1064    ///
1065    /// let response = Response::new(200, "Hello, world!")
1066    ///     .mime(mime::TEXT_PLAIN);
1067    /// # }
1068    /// ```
1069    #[cfg(feature = "mime")]
1070    pub fn mime(mut self, mime: mime::Mime) -> Self {
1071        self.insert_header(
1072            http::header::CONTENT_TYPE,
1073            http::HeaderValue::from_str(mime.as_ref()).unwrap(),
1074        );
1075        self
1076    }
1077
1078    /// Parses the `Content-Type` header and returns a MIME type.
1079    ///
1080    /// This method attempts to parse the `Content-Type` header value as a MIME type,
1081    /// providing structured access to content type information.
1082    ///
1083    /// # Returns
1084    ///
1085    /// Returns `Some(mime::Mime)` if the header exists and can be parsed,
1086    /// or `None` if the header is missing or invalid.
1087    ///
1088    /// # Examples
1089    ///
1090    /// ```rust
1091    /// # #[cfg(feature = "mime")]
1092    /// # {
1093    /// use http_kit::Response;
1094    /// use mime;
1095    ///
1096    /// let response = Response::new(200, "Hello")
1097    ///     .header(http::header::CONTENT_TYPE, "text/plain; charset=utf-8");
1098    ///
1099    /// if let Some(mime_type) = response.get_mime() {
1100    ///     assert_eq!(mime_type.type_(), mime::TEXT);
1101    ///     assert_eq!(mime_type.subtype(), mime::PLAIN);
1102    /// }
1103    /// # }
1104    /// ```
1105    #[cfg(feature = "mime")]
1106    pub fn get_mime(&self) -> Option<mime::Mime> {
1107        core::str::from_utf8(self.get_header(http::header::CONTENT_TYPE)?.as_bytes())
1108            .ok()?
1109            .parse()
1110            .ok()
1111    }
1112}