pub struct Body { /* private fields */ }Expand description
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.
| Constructor | Into |
|---|---|
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.
§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§
Source§impl Body
impl Body
Sourcepub fn empty() -> Self
pub fn empty() -> Self
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();Sourcepub fn from_str(text: &str) -> Self
pub fn from_str(text: &str) -> Self
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();Sourcepub fn from_string(text: String) -> Self
pub fn from_string(text: String) -> Self
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();Sourcepub fn from_bytes(bytes: &[u8]) -> Self
pub fn from_bytes(bytes: &[u8]) -> Self
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();Sourcepub fn from_vec(bytes: Vec<u8>) -> Self
pub fn from_vec(bytes: Vec<u8>) -> Self
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();Sourcepub fn from_file(file: File) -> Self
pub fn from_file(file: File) -> Self
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. Uses content-type from the headers if set , and
falls back to application/octet-stream.
§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();Sourcepub fn from_json<B: Serialize + ?Sized>(json: &B) -> Self
pub fn from_json<B: Serialize + ?Sized>(json: &B) -> Self
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);Sourcepub fn from_async_read<R>(reader: R, length: Option<u64>) -> Self
pub fn from_async_read<R>(reader: R, length: Option<u64>) -> Self
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.
Sourcepub fn from_sync_read<R>(reader: R, length: Option<u64>) -> Self
pub fn from_sync_read<R>(reader: R, length: Option<u64>) -> Self
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.
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.
Sourcepub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>
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("http://httpbin.org/html")
.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>");Sourcepub async fn read_to_vec(&mut self) -> Result<Vec<u8>, Error>
pub async fn read_to_vec(&mut self) -> Result<Vec<u8>, Error>
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("http://httpbin.org/html")
.call().block().unwrap();
let data = resp.body_mut().read_to_vec().block().unwrap();
assert_eq!(&data[..15], b"<!DOCTYPE html>");Sourcepub async fn read_to_string(&mut self) -> Result<String, Error>
pub async fn read_to_string(&mut self) -> Result<String, Error>
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("http://httpbin.org/html")
.call().block().unwrap();
let data = resp.body_mut().read_to_string().block().unwrap();
assert_eq!(&data[..15], "<!DOCTYPE html>");Sourcepub async fn read_to_json<T: DeserializeOwned>(&mut self) -> Result<T, Error>
pub async fn read_to_json<T: DeserializeOwned>(&mut self) -> Result<T, Error>
Sourcepub async fn read_and_discard(&mut self) -> Result<(), Error>
pub async fn read_and_discard(&mut self) -> Result<(), Error>
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://httpbin.org/get")
.call().block().unwrap();
resp.body_mut().read_and_discard();Trait Implementations§
Source§impl AsyncRead for Body
impl AsyncRead for Body
Auto Trait Implementations§
impl !Freeze for Body
impl !RefUnwindSafe for Body
impl Send for Body
impl Sync for Body
impl Unpin for Body
impl !UnwindSafe for Body
Blanket Implementations§
Source§impl<R> AsyncReadExt for R
impl<R> AsyncReadExt for R
Source§fn chain<R>(self, next: R) -> Chain<Self, R>
fn chain<R>(self, next: R) -> Chain<Self, R>
Source§fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>where
Self: Unpin,
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>where
Self: Unpin,
buf in asynchronous
manner, returning a future type. Read moreSource§fn read_vectored<'a>(
&'a mut self,
bufs: &'a mut [IoSliceMut<'a>],
) -> ReadVectored<'a, Self>where
Self: Unpin,
fn read_vectored<'a>(
&'a mut self,
bufs: &'a mut [IoSliceMut<'a>],
) -> ReadVectored<'a, Self>where
Self: Unpin,
AsyncRead into bufs using vectored
IO operations. Read moreSource§fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>where
Self: Unpin,
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>where
Self: Unpin,
buf,
returning an error if end of file (EOF) is hit sooner. Read moreSource§fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>where
Self: Unpin,
fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>where
Self: Unpin,
AsyncRead. Read moreSource§fn read_to_string<'a>(
&'a mut self,
buf: &'a mut String,
) -> ReadToString<'a, Self>where
Self: Unpin,
fn read_to_string<'a>(
&'a mut self,
buf: &'a mut String,
) -> ReadToString<'a, Self>where
Self: Unpin,
AsyncRead. Read more