@@ -113,6 +113,23 @@ impl Body {
113
113
}
114
114
}
115
115
116
+ /// Get the inner reader from the `Body`
117
+ ///
118
+ /// # Examples
119
+ ///
120
+ /// ```
121
+ /// # use std::io::prelude::*;
122
+ /// use http_types::Body;
123
+ /// use async_std::io::Cursor;
124
+ ///
125
+ /// let cursor = Cursor::new("Hello Nori");
126
+ /// let body = Body::from_reader(cursor, None);
127
+ /// let _ = body.into_reader();
128
+ /// ```
129
+ pub fn into_reader ( self ) -> Box < dyn BufRead + Unpin + Send + ' static > {
130
+ self . reader
131
+ }
132
+
116
133
/// Create a `Body` from a Vec of bytes.
117
134
///
118
135
/// The Mime type is set to `application/octet-stream` if no other mime type has been set or can
@@ -160,6 +177,54 @@ impl Body {
160
177
Ok ( buf)
161
178
}
162
179
180
+ /// Create a `Body` from a String
181
+ ///
182
+ /// The Mime type is set to `text/plain` if no other mime type has been set or can
183
+ /// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to
184
+ /// framed messages such as [Chunked
185
+ /// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding).
186
+ ///
187
+ /// # Examples
188
+ ///
189
+ /// ```
190
+ /// use http_types::{Body, Response, StatusCode};
191
+ /// use async_std::io::Cursor;
192
+ ///
193
+ /// let mut req = Response::new(StatusCode::Ok);
194
+ ///
195
+ /// let input = String::from("hello Nori!");
196
+ /// req.set_body(Body::from_bytes(input));
197
+ /// ```
198
+ pub fn from_string ( s : String ) -> Self {
199
+ Self {
200
+ mime : mime:: PLAIN ,
201
+ length : Some ( s. len ( ) ) ,
202
+ reader : Box :: new ( io:: Cursor :: new ( s. into_bytes ( ) ) ) ,
203
+ }
204
+ }
205
+
206
+ /// Read the body as a string
207
+ ///
208
+ /// # Examples
209
+ ///
210
+ /// ```
211
+ /// # use std::io::prelude::*;
212
+ /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
213
+ /// # async_std::task::block_on(async {
214
+ /// use http_types::Body;
215
+ /// use async_std::io::Cursor;
216
+ ///
217
+ /// let cursor = Cursor::new("Hello Nori");
218
+ /// let body = Body::from_reader(cursor, None);
219
+ /// assert_eq!(&body.into_string().await.unwrap(), "Hello Nori");
220
+ /// # Ok(()) }) }
221
+ /// ```
222
+ pub async fn into_string ( mut self ) -> io:: Result < String > {
223
+ let mut result = String :: with_capacity ( self . len ( ) . unwrap_or ( 0 ) ) ;
224
+ self . read_to_string ( & mut result) . await ?;
225
+ Ok ( result)
226
+ }
227
+
163
228
/// Creates a `Body` from a type, serializing it as JSON.
164
229
///
165
230
/// # Mime
@@ -171,10 +236,10 @@ impl Body {
171
236
/// ```
172
237
/// use http_types::{Body, convert::json};
173
238
///
174
- /// let body = Body::from_json(json!({ "name": "Chashu" }));
239
+ /// let body = Body::from_json(& json!({ "name": "Chashu" }));
175
240
/// # drop(body);
176
241
/// ```
177
- pub fn from_json ( json : impl Serialize ) -> crate :: Result < Self > {
242
+ pub fn from_json ( json : & impl Serialize ) -> crate :: Result < Self > {
178
243
let bytes = serde_json:: to_vec ( & json) ?;
179
244
let body = Self {
180
245
length : Some ( bytes. len ( ) ) ,
@@ -184,6 +249,99 @@ impl Body {
184
249
Ok ( body)
185
250
}
186
251
252
+ /// Parse the body as JSON, serializing it to a struct.
253
+ ///
254
+ /// # Examples
255
+ ///
256
+ /// ```
257
+ /// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
258
+ /// use http_types::Body;
259
+ /// use http_types::convert::{Serialize, Deserialize};
260
+ ///
261
+ /// #[derive(Debug, Serialize, Deserialize)]
262
+ /// struct Cat { name: String }
263
+ ///
264
+ /// let cat = Cat { name: String::from("chashu") };
265
+ /// let body = Body::from_json(cat)?;
266
+ ///
267
+ /// let cat: Cat = body.into_json().await?;
268
+ /// assert_eq!(&cat.name, "chashu");
269
+ /// # Ok(()) }) }
270
+ /// ```
271
+ pub async fn into_json < T : DeserializeOwned > ( mut self ) -> crate :: Result < T > {
272
+ let mut buf = Vec :: with_capacity ( 1024 ) ;
273
+ self . read_to_end ( & mut buf) . await ?;
274
+ Ok ( serde_json:: from_slice ( & buf) . map_err ( io:: Error :: from) ?)
275
+ }
276
+
277
+ /// Creates a `Body` from a type, serializing it using form encoding.
278
+ ///
279
+ /// # Mime
280
+ ///
281
+ /// The encoding is set to `application/x-www-form-urlencoded`.
282
+ ///
283
+ /// # Errors
284
+ ///
285
+ /// An error will be returned if the encoding failed.
286
+ ///
287
+ /// # Examples
288
+ ///
289
+ /// ```
290
+ /// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
291
+ /// use http_types::Body;
292
+ /// use http_types::convert::{Serialize, Deserialize};
293
+ ///
294
+ /// #[derive(Debug, Serialize, Deserialize)]
295
+ /// struct Cat { name: String }
296
+ ///
297
+ /// let cat = Cat { name: String::from("chashu") };
298
+ /// let body = Body::from_form(&cat)?;
299
+ ///
300
+ /// let cat: Cat = body.into_form().await?;
301
+ /// assert_eq!(&cat.name, "chashu");
302
+ /// # Ok(()) }) }
303
+ /// ```
304
+ pub fn from_form ( form : & impl Serialize ) -> crate :: Result < Self > {
305
+ let query = serde_urlencoded:: to_string ( form) ?;
306
+ let bytes = query. into_bytes ( ) ;
307
+
308
+ let body = Self {
309
+ length : Some ( bytes. len ( ) ) ,
310
+ reader : Box :: new ( Cursor :: new ( bytes) ) ,
311
+ mime : mime:: FORM ,
312
+ } ;
313
+ Ok ( body)
314
+ }
315
+
316
+ /// Parse the body from form encoding into a type.
317
+ ///
318
+ /// # Errors
319
+ ///
320
+ /// An error is returned if the underlying IO stream errors, or if the body
321
+ /// could not be deserialized into the type.
322
+ ///
323
+ /// # Examples
324
+ ///
325
+ /// ```
326
+ /// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
327
+ /// use http_types::Body;
328
+ /// use http_types::convert::{Serialize, Deserialize};
329
+ ///
330
+ /// #[derive(Debug, Serialize, Deserialize)]
331
+ /// struct Cat { name: String }
332
+ ///
333
+ /// let cat = Cat { name: String::from("chashu") };
334
+ /// let body = Body::from_form(cat)?;
335
+ ///
336
+ /// let cat: Cat = body.into_form().await?;
337
+ /// assert_eq!(&cat.name, "chashu");
338
+ /// # Ok(()) }) }
339
+ /// ```
340
+ pub async fn into_form < T : DeserializeOwned > ( self ) -> crate :: Result < T > {
341
+ let s = self . into_string ( ) . await ?;
342
+ Ok ( serde_urlencoded:: from_str ( & s) ?)
343
+ }
344
+
187
345
/// Create a `Body` from a file.
188
346
///
189
347
/// The Mime type set to `application/octet-stream` if no other mime type has
@@ -230,70 +388,6 @@ impl Body {
230
388
self . length . map ( |length| length == 0 )
231
389
}
232
390
233
- /// Get the inner reader from the `Body`
234
- ///
235
- /// # Examples
236
- ///
237
- /// ```
238
- /// # use std::io::prelude::*;
239
- /// use http_types::Body;
240
- /// use async_std::io::Cursor;
241
- ///
242
- /// let cursor = Cursor::new("Hello Nori");
243
- /// let body = Body::from_reader(cursor, None);
244
- /// let _ = body.into_reader();
245
- /// ```
246
- pub fn into_reader ( self ) -> Box < dyn BufRead + Unpin + Send + ' static > {
247
- self . reader
248
- }
249
-
250
- /// Read the body as a string
251
- ///
252
- /// # Examples
253
- ///
254
- /// ```
255
- /// # use std::io::prelude::*;
256
- /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
257
- /// # async_std::task::block_on(async {
258
- /// use http_types::Body;
259
- /// use async_std::io::Cursor;
260
- ///
261
- /// let cursor = Cursor::new("Hello Nori");
262
- /// let body = Body::from_reader(cursor, None);
263
- /// assert_eq!(&body.into_string().await.unwrap(), "Hello Nori");
264
- /// # Ok(()) }) }
265
- /// ```
266
- pub async fn into_string ( mut self ) -> io:: Result < String > {
267
- let mut result = String :: with_capacity ( self . len ( ) . unwrap_or ( 0 ) ) ;
268
- self . read_to_string ( & mut result) . await ?;
269
- Ok ( result)
270
- }
271
-
272
- /// Parse the body as JSON, serializing it to a struct.
273
- ///
274
- /// # Examples
275
- ///
276
- /// ```
277
- /// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
278
- /// use http_types::Body;
279
- /// use http_types::convert::{Serialize, Deserialize};
280
- ///
281
- /// #[derive(Debug, Serialize, Deserialize)]
282
- /// struct Cat { name: String }
283
- ///
284
- /// let cat = Cat { name: String::from("chashu") };
285
- /// let body = Body::from_json(cat)?;
286
- ///
287
- /// let cat: Cat = body.into_json().await?;
288
- /// assert_eq!(&cat.name, "chashu");
289
- /// # Ok(()) }) }
290
- /// ```
291
- pub async fn into_json < T : DeserializeOwned > ( mut self ) -> crate :: Result < T > {
292
- let mut buf = Vec :: with_capacity ( 1024 ) ;
293
- self . read_to_end ( & mut buf) . await ?;
294
- Ok ( serde_json:: from_slice ( & buf) . map_err ( io:: Error :: from) ?)
295
- }
296
-
297
391
pub ( crate ) fn mime ( & self ) -> & Mime {
298
392
& self . mime
299
393
}
@@ -310,59 +404,25 @@ impl Debug for Body {
310
404
311
405
impl From < String > for Body {
312
406
fn from ( s : String ) -> Self {
313
- Self {
314
- length : Some ( s. len ( ) ) ,
315
- reader : Box :: new ( Cursor :: new ( s. into_bytes ( ) ) ) ,
316
- mime : mime:: PLAIN ,
317
- }
407
+ Self :: from_string ( s)
318
408
}
319
409
}
320
410
321
411
impl < ' a > From < & ' a str > for Body {
322
412
fn from ( s : & ' a str ) -> Self {
323
- Self {
324
- length : Some ( s. len ( ) ) ,
325
- reader : Box :: new ( Cursor :: new ( s. to_owned ( ) . into_bytes ( ) ) ) ,
326
- mime : mime:: PLAIN ,
327
- }
413
+ Self :: from_string ( s. to_owned ( ) )
328
414
}
329
415
}
330
416
331
417
impl From < Vec < u8 > > for Body {
332
418
fn from ( b : Vec < u8 > ) -> Self {
333
- Self {
334
- length : Some ( b. len ( ) ) ,
335
- reader : Box :: new ( Cursor :: new ( b) ) ,
336
- mime : mime:: BYTE_STREAM ,
337
- }
419
+ Self :: from_bytes ( b. to_owned ( ) )
338
420
}
339
421
}
340
422
341
423
impl < ' a > From < & ' a [ u8 ] > for Body {
342
424
fn from ( b : & ' a [ u8 ] ) -> Self {
343
- Self {
344
- length : Some ( b. len ( ) ) ,
345
- reader : Box :: new ( io:: Cursor :: new ( b. to_owned ( ) ) ) ,
346
- mime : mime:: BYTE_STREAM ,
347
- }
348
- }
349
- }
350
-
351
- #[ cfg( feature = "async_std" ) ]
352
- impl From < async_std:: fs:: File > for Body {
353
- fn from ( file : async_std:: fs:: File ) -> Self {
354
- let length = async_std:: task:: block_on ( async {
355
- file. metadata ( )
356
- . await
357
- . expect ( "unable to read file metadata" )
358
- . len ( )
359
- } ) ;
360
-
361
- Self {
362
- length : Some ( length as usize ) ,
363
- reader : Box :: new ( async_std:: io:: BufReader :: new ( file) ) ,
364
- mime : mime:: BYTE_STREAM ,
365
- }
425
+ Self :: from_bytes ( b. to_owned ( ) )
366
426
}
367
427
}
368
428
0 commit comments