Coverage Report

Created: 2026-03-23 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/axum-0.8.8/src/response/mod.rs
Line
Count
Source
1
#![doc = include_str!("../docs/response.md")]
2
3
use http::{header, HeaderValue, StatusCode};
4
5
mod redirect;
6
7
pub mod sse;
8
9
#[doc(no_inline)]
10
#[cfg(feature = "json")]
11
pub use crate::Json;
12
13
#[cfg(feature = "form")]
14
#[doc(no_inline)]
15
pub use crate::form::Form;
16
17
#[doc(no_inline)]
18
pub use crate::Extension;
19
20
#[doc(inline)]
21
pub use axum_core::response::{
22
    AppendHeaders, ErrorResponse, IntoResponse, IntoResponseParts, Response, ResponseParts, Result,
23
};
24
25
#[doc(inline)]
26
pub use self::redirect::Redirect;
27
28
#[doc(inline)]
29
pub use sse::Sse;
30
31
/// An HTML response.
32
///
33
/// Will automatically get `Content-Type: text/html`.
34
#[derive(Clone, Copy, Debug)]
35
#[must_use]
36
pub struct Html<T>(pub T);
37
38
impl<T> IntoResponse for Html<T>
39
where
40
    T: IntoResponse,
41
{
42
0
    fn into_response(self) -> Response {
43
0
        (
44
0
            [(
45
0
                header::CONTENT_TYPE,
46
0
                HeaderValue::from_static(mime::TEXT_HTML_UTF_8.as_ref()),
47
0
            )],
48
0
            self.0,
49
0
        )
50
0
            .into_response()
51
0
    }
52
}
53
54
impl<T> From<T> for Html<T> {
55
0
    fn from(inner: T) -> Self {
56
0
        Self(inner)
57
0
    }
58
}
59
60
/// An empty response with 204 No Content status.
61
///
62
/// Due to historical and implementation reasons, the `IntoResponse` implementation of `()`
63
/// (unit type) returns an empty response with 200 [`StatusCode::OK`] status.
64
/// If you specifically want a 204 [`StatusCode::NO_CONTENT`] status, you can use either `StatusCode` type
65
/// directly, or this shortcut struct for self-documentation.
66
///
67
/// ```
68
/// use axum::{extract::Path, response::NoContent};
69
///
70
/// async fn delete_user(Path(user): Path<String>) -> Result<NoContent, String> {
71
///     // ...access database...
72
/// # drop(user);
73
///     Ok(NoContent)
74
/// }
75
/// ```
76
#[derive(Debug, Clone, Copy)]
77
pub struct NoContent;
78
79
impl IntoResponse for NoContent {
80
0
    fn into_response(self) -> Response {
81
0
        StatusCode::NO_CONTENT.into_response()
82
0
    }
83
}
84
85
#[cfg(test)]
86
mod tests {
87
    use crate::extract::Extension;
88
    use crate::{routing::get, Router};
89
    use axum_core::response::IntoResponse;
90
    use http::HeaderMap;
91
    use http::{StatusCode, Uri};
92
93
    // just needs to compile
94
    #[allow(dead_code)]
95
    fn impl_trait_result_works() {
96
        async fn impl_trait_ok() -> Result<impl IntoResponse, ()> {
97
            Ok(())
98
        }
99
100
        async fn impl_trait_err() -> Result<(), impl IntoResponse> {
101
            Err(())
102
        }
103
104
        async fn impl_trait_both(uri: Uri) -> Result<impl IntoResponse, impl IntoResponse> {
105
            if uri.path() == "/" {
106
                Ok(())
107
            } else {
108
                Err(())
109
            }
110
        }
111
112
        async fn impl_trait(uri: Uri) -> impl IntoResponse {
113
            if uri.path() == "/" {
114
                Ok(())
115
            } else {
116
                Err(())
117
            }
118
        }
119
120
        _ = Router::<()>::new()
121
            .route("/", get(impl_trait_ok))
122
            .route("/", get(impl_trait_err))
123
            .route("/", get(impl_trait_both))
124
            .route("/", get(impl_trait));
125
    }
126
127
    // just needs to compile
128
    #[allow(dead_code)]
129
    fn tuple_responses() {
130
        async fn status() -> impl IntoResponse {
131
            StatusCode::OK
132
        }
133
134
        async fn status_headermap() -> impl IntoResponse {
135
            (StatusCode::OK, HeaderMap::new())
136
        }
137
138
        async fn status_header_array() -> impl IntoResponse {
139
            (StatusCode::OK, [("content-type", "text/plain")])
140
        }
141
142
        async fn status_headermap_body() -> impl IntoResponse {
143
            (StatusCode::OK, HeaderMap::new(), String::new())
144
        }
145
146
        async fn status_header_array_body() -> impl IntoResponse {
147
            (
148
                StatusCode::OK,
149
                [("content-type", "text/plain")],
150
                String::new(),
151
            )
152
        }
153
154
        async fn status_headermap_impl_into_response() -> impl IntoResponse {
155
            (StatusCode::OK, HeaderMap::new(), impl_into_response())
156
        }
157
158
        async fn status_header_array_impl_into_response() -> impl IntoResponse {
159
            (
160
                StatusCode::OK,
161
                [("content-type", "text/plain")],
162
                impl_into_response(),
163
            )
164
        }
165
166
        fn impl_into_response() -> impl IntoResponse {}
167
168
        async fn status_header_array_extension_body() -> impl IntoResponse {
169
            (
170
                StatusCode::OK,
171
                [("content-type", "text/plain")],
172
                Extension(1),
173
                String::new(),
174
            )
175
        }
176
177
        async fn status_header_array_extension_mixed_body() -> impl IntoResponse {
178
            (
179
                StatusCode::OK,
180
                [("content-type", "text/plain")],
181
                Extension(1),
182
                HeaderMap::new(),
183
                String::new(),
184
            )
185
        }
186
187
        //
188
189
        async fn headermap() -> impl IntoResponse {
190
            HeaderMap::new()
191
        }
192
193
        async fn header_array() -> impl IntoResponse {
194
            [("content-type", "text/plain")]
195
        }
196
197
        async fn headermap_body() -> impl IntoResponse {
198
            (HeaderMap::new(), String::new())
199
        }
200
201
        async fn header_array_body() -> impl IntoResponse {
202
            ([("content-type", "text/plain")], String::new())
203
        }
204
205
        async fn headermap_impl_into_response() -> impl IntoResponse {
206
            (HeaderMap::new(), impl_into_response())
207
        }
208
209
        async fn header_array_impl_into_response() -> impl IntoResponse {
210
            ([("content-type", "text/plain")], impl_into_response())
211
        }
212
213
        async fn header_array_extension_body() -> impl IntoResponse {
214
            (
215
                [("content-type", "text/plain")],
216
                Extension(1),
217
                String::new(),
218
            )
219
        }
220
221
        async fn header_array_extension_mixed_body() -> impl IntoResponse {
222
            (
223
                [("content-type", "text/plain")],
224
                Extension(1),
225
                HeaderMap::new(),
226
                String::new(),
227
            )
228
        }
229
230
        _ = Router::<()>::new()
231
            .route("/", get(status))
232
            .route("/", get(status_headermap))
233
            .route("/", get(status_header_array))
234
            .route("/", get(status_headermap_body))
235
            .route("/", get(status_header_array_body))
236
            .route("/", get(status_headermap_impl_into_response))
237
            .route("/", get(status_header_array_impl_into_response))
238
            .route("/", get(status_header_array_extension_body))
239
            .route("/", get(status_header_array_extension_mixed_body))
240
            .route("/", get(headermap))
241
            .route("/", get(header_array))
242
            .route("/", get(headermap_body))
243
            .route("/", get(header_array_body))
244
            .route("/", get(headermap_impl_into_response))
245
            .route("/", get(header_array_impl_into_response))
246
            .route("/", get(header_array_extension_body))
247
            .route("/", get(header_array_extension_mixed_body));
248
    }
249
250
    #[test]
251
    fn no_content() {
252
        assert_eq!(
253
            super::NoContent.into_response().status(),
254
            StatusCode::NO_CONTENT,
255
        )
256
    }
257
}