[][src]Struct hreq::Body

pub struct Body { /* fields omitted */ }

Body of an http request or response.

Creating a body

Bodies are created either by using a constructor function, or the Into trait. The into trait can be used where rust knows the result should be Body such as in the request builder .send().

use hreq::prelude::*;

let res = Request::post("https://post-to-server/")
    // send has Into<Body> type, which means we can
    // provide the Into type straight up
    .send("some body content")
    .block().unwrap();

Or if we use .into() explcitly.

use hreq::Body;

// call into() to get a Body
let body: Body = "some body content".into();

The constructor with corresponding expression usable with Into.

ConstructorInto
Body::empty()()
Body::from_str("abc")"abc"
Body::from_string("abc".to_string())"abc".to_string()
Body::from_bytes(&[42_u8, 43_u8])&[42_u8, 43_u8]
Body::from_vec(vec![42_u8, 43_u8])vec![42_u8, 43_u8]
Body::from_file(file)file
Body::from_async_read(reader, None)-
Body::from_sync_read(reader, None)-

Readers and performance

The most performant way provide a large body is as an AsyncRead. It will be streamed through hreq without using up too much memory.

Sync readers risks blocking the async runtime. This is not a big concern if the reader is something like a std::io::Cursor over a slice of memory, or maybe even a std::fs::File with a fast disk. Choice of runtime also matters; async-std tries to automatically "parry" blocking operations. Use sync readers with caution and prefer async readers.

charset encoding

hreq automatically encodes the request body's character encoding for MIME types starting text/.

The mechanic is triggered by setting a content-type request header with the charset that is wanted:

  • content-type: text/html charset=iso8859-1

The source material encoding is assumed to be utf-8 unless changed by charset_encode_source.

The behavior can be completely disabled using charset_encode.

compression

hreq can compress the request body. The mechanic is triggered by setting a content-encoding header with the compression algorithm.

  • content-encoding: gzip

The only supported algorithm is gzip.

Reading a body

hreq provides a number of ways to read the contents of a body.

Finaly Body implements AsyncRead, which means that in many cases, it can be used as is in rust's async ecosystem.

use hreq::prelude::*;
use futures_util::io::AsyncReadExt;

let res = Request::get("https://my-special-host/")
    .call().block().unwrap();

let mut body = res.into_body();
let mut first_ten = vec![0_u8; 10];
// read_exact comes from AsyncReadExt
body.read_exact(&mut first_ten[..]).block().unwrap();

charset decoding

hreq automatically decodes the response body's character encoding for MIME types starting text/.

The mechanic is triggered by receving a content-type response header with the charset of the incoming body:

  • content-type: text/html charset=iso8859-1

The wanted charset is assumed to be utf-8 unless changed by charset_decode_target.

The function can be disabled by using charset_decode.

compression

hreq decompresses the request body. The mechanic is triggered by the presence of a content-encoding: gzip response header.

One can "ask" the server to compress the response by providing a header like accept-encoding: gzip. There's however no guarantee the server will provide compression.

The only supported algorithm is currently gzip.

Implementations

impl Body[src]

pub fn empty() -> Self[src]

Constructs an empty request body.

The content-length is know to be 0 and will be set for requests where a body is expected.

Examples

use hreq::Body;

// The are the same.
let body1: Body = Body::empty();
let body2: Body = ().into();

In Request.send() we can skip the into()

use hreq::prelude::*;

Request::get("https://get-from-here")
    .call().block().unwrap();

pub fn from_str(text: &str) -> Self[src]

Creates a body from a &str by cloning the data.

Will automatically set a content-length header unless compression or chunked encoding is used.

Examples

use hreq::Body;

// The are the same.
let body1: Body = Body::from_str("Hello world");
let body2: Body = "Hello world".into();

In Request.send() we can skip the into()

use hreq::prelude::*;

Request::post("https://post-to-here")
    .send("Hello world").block().unwrap();

pub fn from_string(text: String) -> Self[src]

Creates a body from a String.

Will automatically set a content-length header unless compression or chunked encoding is used.

Examples

use hreq::Body;

// The are the same.
let body1: Body = Body::from_string("Hello world".to_string());
let body2: Body = "Hello world".to_string().into();

In Request.send() we can skip the into()

use hreq::prelude::*;

Request::post("https://post-to-here")
    .send("Hello world".to_string()).block().unwrap();

pub fn from_bytes(bytes: &[u8]) -> Self[src]

Creates a body from a &[u8] by cloning the data.

Will automatically set a content-length header unless compression or chunked encoding is used.

Examples

use hreq::Body;

let data = [0x42, 0x43];

// The are the same.
let body1: Body = Body::from_bytes(&data[..]);
let body2: Body = (&data[..]).into();

In Request.send() we can skip the into()

use hreq::prelude::*;

let data = [0x42, 0x43];

Request::post("https://post-to-here")
    .send(&data[..]).block().unwrap();

pub fn from_vec(bytes: Vec<u8>) -> Self[src]

Creates a body from a Vec<u8>.

Will automatically set a content-length header unless compression or chunked encoding is used.

Examples

use hreq::Body;

// The are the same.
let body1: Body = Body::from_vec(vec![0x42, 0x43]);
let body2: Body = vec![0x42, 0x43].into();

In Request.send() we can skip the into()

use hreq::prelude::*;

Request::post("https://post-to-here")
    .send(vec![0x42, 0x43]).block().unwrap();

pub fn from_file(file: File) -> Self[src]

Creates a body from a std::fs::File.

Despite the std origins, hreq will send this efficiently by reading the file in a non-blocking way.

The request will have a content-length header unless compression or chunked encoding is used.

Examples

use hreq::Body;
use std::fs::File;

// The are the same.
let body1: Body = Body::from_file(File::open("myfile.txt").unwrap());
let body2: Body = File::open("myfile.txt").unwrap().into();

In Request.send() we can skip the into()

use hreq::prelude::*;
use std::fs::File;

Request::post("https://post-to-here")
    .send(File::open("myfile.txt").unwrap()).block().unwrap();

pub fn from_json<B: Serialize + ?Sized>(json: &B) -> Self[src]

Creates a body from a JSON encodable type.

This also sets the content-type and content-length headers.

Example

use hreq::Body;
use serde_derive::Serialize;

#[derive(Serialize)]
struct MyJsonThing {
  name: String,
  age: u8,
}

let json = MyJsonThing {
  name: "Karl Kajal".to_string(),
  age: 32,
};

let body = Body::from_json(&json);

pub fn from_async_read<R>(reader: R, length: Option<u64>) -> Self where
    R: AsyncRead + Unpin + Send + Sync + 'static, 
[src]

Creates a body from anything implementing the AsyncRead trait.

This is a very efficient way of sending bodies since the content

The content-length header will be set depending on whether a length is provided. Combinations of charset and compression might make it so content-length is not known despite being provided.

pub fn from_sync_read<R>(reader: R, length: Option<u64>) -> Self where
    R: Read + Send + Sync + 'static, 
[src]

Creates a body from anything implementing the (blocking) std::io::Read trait.

Might block the async runtime, so whether using this is a good idea depends on circumstances. If the Read is just an std::io::Cursor over some memory or very fast file system, it might be ok. Some runtimes like async-std further have ways of detecting blocking operations.

Use with care.

The content-length header will be set depending on whether a length is provided. Combinations of charset and compression might make it so content-length is not known despite being provided.

pub async fn read<'_, '_>(
    &'_ mut self,
    buf: &'_ mut [u8]
) -> Result<usize, Error>
[src]

Read some bytes from this body into the specified buffer, returning how many bytes were read.

If the returned amount is 0, the end of the body has been reached.

See charset_decode and charset_decode_target of headers and options that will affect text/ MIME types.

Examples

use hreq::prelude::*;

let mut resp = Request::get("https://www.google.com")
    .call().block().unwrap();

let mut data = vec![0_u8; 100];

let amount = resp.body_mut().read(&mut data[..]).block().unwrap();

assert!(amount >= 15);
assert_eq!(&data[..15], b"<!doctype html>");

pub async fn read_to_vec<'_>(&'_ mut self) -> Result<Vec<u8>, Error>[src]

Reads to body to end into a new Vec.

This can potentially take up a lot of memory (or even exhaust your RAM), depending on how big the response body is.

See charset_decode and charset_decode_target of headers and options that will affect text/ MIME types.

Examples

use hreq::prelude::*;

let mut resp = Request::get("https://www.google.com")
    .call().block().unwrap();

let data = resp.body_mut().read_to_vec().block().unwrap();

assert_eq!(&data[..15], b"<!doctype html>");

pub async fn read_to_string<'_>(&'_ mut self) -> Result<String, Error>[src]

Reads to body to end into a new String.

This can potentially take up a lot of memory (or even exhaust your RAM), depending on how big the response body is.

Since a rust string is always utf-8, charset_decode_target is ignored.

Panics if charset_decode is disabled and incoming data is not valid UTF-8.

Examples

use hreq::prelude::*;

let mut resp = Request::get("https://www.google.com")
    .call().block().unwrap();

let data = resp.body_mut().read_to_string().block().unwrap();

assert_eq!(&data[..15], "<!doctype html>");

pub async fn read_to_json<T: DeserializeOwned, '_>(
    &'_ mut self
) -> Result<T, Error>
[src]

Reads to body to end as a JSON string into a deserialized object.

Examples

This example is not tested
use hreq::Body;
use serde_derive::Deserialize;

#[derive(Deserialize)]
struct MyJsonThing {
  name: String,
  age: String,
}

let req: MyJsonThing = Request::get("http://foo")
  .call().block().unwrap()
  .read_json().unwrap();

pub async fn read_to_end<'_>(&'_ mut self) -> Result<(), Error>[src]

Reads to body to end and discards it.

HTTP/1.1 has no "multiplexing" of several concurrent request over the same socket; One must read the previous request's body to end before being able to read the next response header.

For pooled connections we can't reuse the connection until the previous body has been exhausted.

Examples

use hreq::prelude::*;

let mut resp = Request::get("https://www.google.com")
    .call().block().unwrap();

resp.body_mut().read_to_end();

Trait Implementations

impl AsyncRead for Body[src]

impl Debug for Body[src]

impl<'a> From<&'a [u8]> for Body[src]

impl<'a> From<&'a String> for Body[src]

impl<'a> From<&'a Vec<u8>> for Body[src]

impl<'a> From<&'a str> for Body[src]

impl From<()> for Body[src]

impl From<Body> for Reply[src]

impl From<File> for Body[src]

impl From<String> for Body[src]

impl From<Vec<u8>> for Body[src]

Auto Trait Implementations

impl !RefUnwindSafe for Body

impl Send for Body

impl Sync for Body

impl Unpin for Body

impl !UnwindSafe for Body

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<R> AsyncReadExt for R where
    R: AsyncRead + ?Sized
[src]

impl<R> AsyncReadExt for R where
    R: AsyncRead + ?Sized

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ReadExt for T where
    T: AsyncRead + ?Sized

impl<T> Sealed<T> for T where
    T: ?Sized

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> WithSubscriber for T[src]