Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conversions to and from bytes #100

Merged
merged 1 commit into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/body.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use async_std::io::prelude::*;
use async_std::io::{self, BufRead, Read};

use std::fmt::{self, Debug};
Expand Down Expand Up @@ -81,7 +82,7 @@ impl Body {

/// Create a `Body` from a reader with an optional length.
///
/// The Mime type set to `application/octet-stream` if no other mime type has been set or can
/// The Mime type is set to `application/octet-stream` if no other mime type has been set or can
/// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to
/// framed messages such as [Chunked
/// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding).
Expand Down Expand Up @@ -109,6 +110,53 @@ impl Body {
}
}

/// Create a `Body` from a Vec of bytes.
///
/// The Mime type is set to `application/octet-stream` if no other mime type has been set or can
/// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to
/// framed messages such as [Chunked
/// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding).
///
/// # Examples
///
/// ```
/// use http_types::{Body, Response, StatusCode};
/// use async_std::io::Cursor;
///
/// let mut req = Response::new(StatusCode::Ok);
///
/// let input = vec![1, 2, 3];
/// req.set_body(Body::from_bytes(input));
/// ```
pub fn from_bytes(bytes: Vec<u8>) -> Self {
Self {
mime: mime::BYTE_STREAM,
length: Some(bytes.len()),
reader: Box::new(io::Cursor::new(bytes)),
}
}

/// Parse the body into a `Vec<u8>`.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
/// use http_types::Body;
///
/// let bytes = vec![1, 2, 3];
/// let body = Body::from_bytes(bytes);
///
/// let bytes: Vec<u8> = body.into_bytes().await?;
/// assert_eq!(bytes, vec![1, 2, 3]);
/// # Ok(()) }) }
/// ```
pub async fn into_bytes(mut self) -> crate::Result<Vec<u8>> {
let mut buf = Vec::with_capacity(1024);
self.read_to_end(&mut buf).await?;
Ok(buf)
}

/// Get the length of the body in bytes.
///
/// # Examples
Expand Down Expand Up @@ -165,7 +213,6 @@ impl Body {
/// # Ok(()) }) }
/// ```
pub async fn into_string(mut self) -> io::Result<String> {
use async_std::io::ReadExt;
let mut result = String::with_capacity(self.len().unwrap_or(0));
self.read_to_string(&mut result).await?;
Ok(result)
Expand Down
25 changes: 25 additions & 0 deletions src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,31 @@ impl Request {
self.body.into_string().await
}

/// Read the body as bytes.
///
/// This consumes the `Request`. If you want to read the body without
/// consuming the request, consider using the `take_body` method and
/// then calling `Body::into_bytes` or using the Request's AsyncRead
/// implementation to read the body.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
/// use http_types::{Body, Url, Method, Request};
///
/// let bytes = vec![1, 2, 3];
/// let mut req = Request::new(Method::Get, Url::parse("https://example.com").unwrap());
/// req.set_body(Body::from_bytes(bytes));
///
/// let bytes = req.body_bytes().await?;
/// assert_eq!(bytes, vec![1, 2, 3]);
/// # Ok(()) }) }
/// ```
pub async fn body_bytes(self) -> crate::Result<Vec<u8>> {
self.body.into_bytes().await
}

/// Get an HTTP header.
pub fn header(&self, name: &HeaderName) -> Option<&Vec<HeaderValue>> {
self.headers.get(name)
Expand Down
26 changes: 26 additions & 0 deletions src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,32 @@ impl Response {
self.body.into_string().await
}

/// Read the body as bytes.
///
/// This consumes the `Response`. If you want to read the body without
/// consuming the response, consider using the `take_body` method and
/// then calling `Body::into_bytes` or using the Response's AsyncRead
/// implementation to read the body.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
///
/// use http_types::{Body, Url, Method, Response, StatusCode};
///
/// let bytes = vec![1, 2, 3];
/// let mut res = Response::new(StatusCode::Ok);
/// res.set_body(Body::from_bytes(bytes));
///
/// let bytes = res.body_bytes().await?;
/// assert_eq!(bytes, vec![1, 2, 3]);
/// # Ok(()) }) }
/// ```
pub async fn body_bytes(self) -> crate::Result<Vec<u8>> {
self.body.into_bytes().await
}

/// Set the response MIME.
pub fn set_content_type(&mut self, mime: Mime) -> Option<Vec<HeaderValue>> {
let value: HeaderValue = mime.into();
Expand Down