Skip to content

Commit 8ff0cae

Browse files
authored
Merge pull request #83 from http-rs/body-mime
Don't move MIME out of the body
2 parents a633448 + fc0c098 commit 8ff0cae

File tree

4 files changed

+64
-23
lines changed

4 files changed

+64
-23
lines changed

src/body.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pin_project_lite::pin_project! {
5252
pub struct Body {
5353
#[pin]
5454
reader: Box<dyn BufRead + Unpin + Send + Sync + 'static>,
55-
mime: Option<Mime>,
55+
mime: Mime,
5656
length: Option<usize>,
5757
}
5858
}
@@ -74,7 +74,7 @@ impl Body {
7474
pub fn empty() -> Self {
7575
Self {
7676
reader: Box::new(io::empty()),
77-
mime: Some(mime::BYTE_STREAM),
77+
mime: mime::BYTE_STREAM,
7878
length: Some(0),
7979
}
8080
}
@@ -104,7 +104,7 @@ impl Body {
104104
) -> Self {
105105
Self {
106106
reader: Box::new(reader),
107-
mime: Some(mime::BYTE_STREAM),
107+
mime: mime::BYTE_STREAM,
108108
length: len,
109109
}
110110
}
@@ -147,9 +147,8 @@ impl Body {
147147
self.reader
148148
}
149149

150-
/// Return the mime type.
151-
pub(crate) fn take_mime(&mut self) -> Mime {
152-
self.mime.take().expect("internal error: missing mime")
150+
pub(crate) fn mime(&self) -> &Mime {
151+
&self.mime
153152
}
154153
}
155154

@@ -167,7 +166,7 @@ impl From<String> for Body {
167166
Self {
168167
length: Some(s.len()),
169168
reader: Box::new(io::Cursor::new(s.into_bytes())),
170-
mime: Some(string_mime()),
169+
mime: string_mime(),
171170
}
172171
}
173172
}
@@ -177,7 +176,7 @@ impl<'a> From<&'a str> for Body {
177176
Self {
178177
length: Some(s.len()),
179178
reader: Box::new(io::Cursor::new(s.to_owned().into_bytes())),
180-
mime: Some(string_mime()),
179+
mime: string_mime(),
181180
}
182181
}
183182
}
@@ -195,7 +194,7 @@ impl From<Vec<u8>> for Body {
195194
Self {
196195
length: Some(b.len()),
197196
reader: Box::new(io::Cursor::new(b)),
198-
mime: Some(mime::BYTE_STREAM),
197+
mime: mime::BYTE_STREAM,
199198
}
200199
}
201200
}

src/request.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,7 @@ impl Request {
111111
/// req.set_body("Hello, Nori!");
112112
/// ```
113113
pub fn set_body(&mut self, body: impl Into<Body>) {
114-
self.body = body.into();
115-
if self.header(&CONTENT_TYPE).is_none() {
116-
let mime = self.body.take_mime();
117-
self.set_content_type(mime);
118-
}
114+
self.replace_body(body);
119115
}
120116

121117
/// Swaps the value of the body with another body, without deinitializing
@@ -141,7 +137,9 @@ impl Request {
141137
/// # Ok(()) }) }
142138
/// ```
143139
pub fn replace_body(&mut self, body: impl Into<Body>) -> Body {
144-
mem::replace(&mut self.body, body.into())
140+
let body = mem::replace(&mut self.body, body.into());
141+
self.copy_content_type_from_body();
142+
body
145143
}
146144

147145
/// Replace the request body with a new body, and return the old body.
@@ -168,6 +166,7 @@ impl Request {
168166
/// ```
169167
pub fn swap_body(&mut self, body: &mut Body) {
170168
mem::swap(&mut self.body, body);
169+
self.copy_content_type_from_body();
171170
}
172171

173172
/// Take the request body, replacing it with an empty body.
@@ -270,6 +269,13 @@ impl Request {
270269
self.insert_header(CONTENT_TYPE, value).unwrap()
271270
}
272271

272+
/// Copy MIME data from the body.
273+
fn copy_content_type_from_body(&mut self) {
274+
if self.header(&CONTENT_TYPE).is_none() {
275+
self.set_content_type(self.body.mime().clone());
276+
}
277+
}
278+
273279
/// Get the current content type
274280
pub fn content_type(&self) -> Option<Mime> {
275281
self.header(&CONTENT_TYPE)?.last()?.as_str().parse().ok()
@@ -446,7 +452,7 @@ impl Request {
446452
/// assert_eq!(req.local().get(), Some(&"hello from the extension"));
447453
/// #
448454
/// # Ok(()) }
449-
/// ```
455+
/// ```
450456
pub fn local_mut(&mut self) -> &mut TypeMap {
451457
&mut self.local
452458
}

src/response.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,7 @@ impl Response {
138138
/// # Ok(()) }
139139
/// ```
140140
pub fn set_body(&mut self, body: impl Into<Body>) {
141-
self.body = body.into();
142-
if self.header(&CONTENT_TYPE).is_none() {
143-
let mime = self.body.take_mime();
144-
self.set_content_type(mime);
145-
}
141+
self.replace_body(body);
146142
}
147143

148144
/// Replace the response body with a new body, returning the old body.
@@ -168,7 +164,9 @@ impl Response {
168164
/// # Ok(()) }) }
169165
/// ```
170166
pub fn replace_body(&mut self, body: impl Into<Body>) -> Body {
171-
mem::replace(&mut self.body, body.into())
167+
let body = mem::replace(&mut self.body, body.into());
168+
self.copy_content_type_from_body();
169+
body
172170
}
173171

174172
/// Swaps the value of the body with another body, without deinitializing
@@ -197,6 +195,7 @@ impl Response {
197195
/// ```
198196
pub fn swap_body(&mut self, body: &mut Body) {
199197
mem::swap(&mut self.body, body);
198+
self.copy_content_type_from_body();
200199
}
201200

202201
/// Take the response body, replacing it with an empty body.
@@ -236,6 +235,13 @@ impl Response {
236235
self.insert_header(CONTENT_TYPE, value).unwrap()
237236
}
238237

238+
/// Copy MIME data from the body.
239+
fn copy_content_type_from_body(&mut self) {
240+
if self.header(&CONTENT_TYPE).is_none() {
241+
self.set_content_type(self.body.mime().clone());
242+
}
243+
}
244+
239245
/// Get the length of the body stream, if it has been set.
240246
///
241247
/// This value is set when passing a fixed-size object into as the body. E.g. a string, or a
@@ -412,7 +418,7 @@ impl Response {
412418
/// assert_eq!(res.local().get(), Some(&"hello from the extension"));
413419
/// #
414420
/// # Ok(()) }
415-
/// ```
421+
/// ```
416422
pub fn local_mut(&mut self) -> &mut TypeMap {
417423
&mut self.local
418424
}

tests/req_res_body.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use async_std::io::prelude::*;
2+
use http_types::{Body, Method, Request, Response, StatusCode, Url};
3+
4+
#[test]
5+
fn test_req_res_set_body() {
6+
let mut req = Request::new(Method::Get, Url::parse("http://example.com/").unwrap());
7+
req.set_body(Body::empty());
8+
let mut res = Response::new(StatusCode::Ok);
9+
res.set_body(req);
10+
let body = async_std::task::block_on(async move {
11+
let mut body = Vec::new();
12+
res.read_to_end(&mut body).await.unwrap();
13+
body
14+
});
15+
assert!(body.is_empty());
16+
}
17+
18+
#[test]
19+
fn test_req_res_take_replace_body() {
20+
let mut req = Request::new(Method::Get, Url::parse("http://example.com/").unwrap());
21+
req.take_body();
22+
let mut res = Response::new(StatusCode::Ok);
23+
res.replace_body(req);
24+
let body = async_std::task::block_on(async move {
25+
let mut body = Vec::new();
26+
res.read_to_end(&mut body).await.unwrap();
27+
body
28+
});
29+
assert!(body.is_empty());
30+
}

0 commit comments

Comments
 (0)