pub struct Call<State> { /* private fields */ }Expand description
A state machine for an HTTP request/response cycle.
This type represents a state machine that transitions through various states during the lifecycle of an HTTP request/response.
The type parameters are:
State: The current state of the state machine (e.g.,Prepare,SendRequest, etc.)
See the state graph in the client module documentation for a visual representation of the state transitions.
Implementations§
Source§impl Call<Prepare>
impl Call<Prepare>
Sourcepub fn new(request: Request<()>) -> Result<Self, Error>
pub fn new(request: Request<()>) -> Result<Self, Error>
Create a new Call instance from an HTTP request.
This initializes a new Call state machine in the Prepare state, setting up the necessary internal state based on the request properties.
Sourcepub fn allow_non_standard_methods(&mut self, v: bool)
pub fn allow_non_standard_methods(&mut self, v: bool)
Set whether to allow non-standard HTTP methods.
By default the methods are limited by the HTTP version.
Sourcepub fn header<K, V>(&mut self, key: K, value: V) -> Result<(), Error>where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<Error>,
pub fn header<K, V>(&mut self, key: K, value: V) -> Result<(), Error>where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<Error>,
Add more headers to the call
Sourcepub fn force_send_body(&mut self)
pub fn force_send_body(&mut self)
Convert the state to send body despite method.
Methods like GET, HEAD and DELETE should not have a request body. Some broken APIs use bodies anyway, and this is an escape hatch to interoperate with such services.
Source§impl Call<SendRequest>
impl Call<SendRequest>
Sourcepub fn write(&mut self, output: &mut [u8]) -> Result<usize, Error>
pub fn write(&mut self, output: &mut [u8]) -> Result<usize, Error>
Write the request to the buffer.
Writes incrementally, it can be called repeatedly in situations where the output buffer is small.
This includes the first row, i.e. GET / HTTP/1.1 and all headers.
The output buffer needs to be large enough for the longest row.
Example:
POST /bar HTTP/1.1\r\n
Host: my.server.test\r\n
User-Agent: myspecialthing\r\n
\r\n
<body data>The buffer would need to be at least 28 bytes big, since the User-Agent row is
28 bytes long.
If the output is too small for the longest line, the result is an OutputOverflow error.
The Ok(usize) is the number of bytes of the output buffer that was used.
Sourcepub fn headers_map(&mut self) -> Result<HeaderMap, Error>
pub fn headers_map(&mut self) -> Result<HeaderMap, Error>
The configured headers.
Sourcepub fn can_proceed(&self) -> bool
pub fn can_proceed(&self) -> bool
Check whether the entire request has been sent.
This is useful when the output buffer is small and we need to repeatedly
call write() to send the entire request.
Source§impl Call<Await100>
impl Call<Await100>
Sourcepub fn try_read_100(&mut self, input: &[u8]) -> Result<usize, Error>
pub fn try_read_100(&mut self, input: &[u8]) -> Result<usize, Error>
Attempt to read a 100-continue response.
Tries to interpret bytes sent by the server as a 100-continue response. The expect-100 mechanic means we hope the server will give us an indication on whether to upload a potentially big request body, before we start doing it.
- If the server supports expect-100, it will respond
HTTP/1.1 100 Continue\r\n\r\n, or some other response code (such as 403) if we are not allowed to post the body. - If the server does not support expect-100, it will not respond at all, in which case we will proceed to sending the request body after some timeout.
The results are:
Ok(0)- not enough data yet, continue waiting (orproceed()if you think we waited enough)Ok(n)-nnumber of input bytes were consumed. Callproceed()nextErr(e)- some error that is not recoverable
Sourcepub fn can_keep_await_100(&self) -> bool
pub fn can_keep_await_100(&self) -> bool
Tell if there is any point in waiting for more data from the server.
Becomes false as soon as try_read_100() got enough data to determine what to do next.
This might become false even if try_read_100 returns Ok(0).
If this returns false, the user should continue with proceed().
Sourcepub fn proceed(self) -> Result<Await100Result, Error>
pub fn proceed(self) -> Result<Await100Result, Error>
Proceed to the next state.
Source§impl Call<SendBody>
impl Call<SendBody>
Sourcepub fn write(
&mut self,
input: &[u8],
output: &mut [u8],
) -> Result<(usize, usize), Error>
pub fn write( &mut self, input: &[u8], output: &mut [u8], ) -> Result<(usize, usize), Error>
Write request body from input to output.
This is called repeatedly until the entire body has been sent. The output buffer is filled as much as possible for each call.
Depending on request headers, the output might be transfer-encoding: chunked. Chunking means
the output is slightly larger than the input due to the extra length headers per chunk.
When not doing chunked, the input/output will be the same per call.
The result (usize, usize) is (input consumed, output used).
Important
To indicate that the body is fully sent, you call write with an input parameter set to &[].
This ends the transfer-encoding: chunked and ensures the state is correct to proceed.
Sourcepub fn consume_direct_write(&mut self, amount: usize) -> Result<(), Error>
pub fn consume_direct_write(&mut self, amount: usize) -> Result<(), Error>
Helper to avoid copying memory.
When the transfer is NOT chunked, write() just copies the input to the output.
This memcopy might be possible to avoid if the user can use the input buffer directly
against the transport.
This function is used to “report” how much of the input that has been used. It’s effectively
the same as the first usize in the pair returned by write().
Sourcepub fn calculate_max_input(&self, output_len: usize) -> usize
pub fn calculate_max_input(&self, output_len: usize) -> usize
Calculate the max amount of input we can transfer to fill the output_len.
For chunked transfer, the input is less than the output.
Sourcepub fn is_chunked(&self) -> bool
pub fn is_chunked(&self) -> bool
Test if call is chunked.
This might need some processing, hence the &mut and
Sourcepub fn can_proceed(&self) -> bool
pub fn can_proceed(&self) -> bool
Check whether the request body is fully sent.
For requests with a content-length header set, this will only become true once the
number of bytes communicated have been sent. For chunked transfer, this becomes true
after calling write() with an input of &[].
Source§impl Call<RecvResponse>
impl Call<RecvResponse>
Sourcepub fn try_response(
&mut self,
input: &[u8],
allow_partial_redirect: bool,
) -> Result<(usize, Option<Response<()>>), Error>
pub fn try_response( &mut self, input: &[u8], allow_partial_redirect: bool, ) -> Result<(usize, Option<Response<()>>), Error>
Try reading a response from the input.
allow_partial_redirect- iftrue, we can accept to find theLocationheader and proceed without reading the entire header. This is useful for broken servers that don’t send an entire \r\n at the end of the preamble.
The (usize, Option<Response()>) is (input amount consumed, response).
Notice that it’s possible that we get an input amount consumed despite not returning
a Some(Response). This can happen if the server returned a 100-continue, and due to
timing reasons we did not receive it while we were in the Await100 call state. This
“spurios” 100 will be discarded before we parse the actual response.
Sourcepub fn can_proceed(&self) -> bool
pub fn can_proceed(&self) -> bool
Tell if we have finished receiving the response.
Sourcepub fn proceed(self) -> Option<RecvResponseResult>
pub fn proceed(self) -> Option<RecvResponseResult>
Proceed to the next state.
This returns None if we have not finished receiving the response. It is guaranteed that if
can_proceed() returns true, this will return Some.
Sourcepub fn force_recv_body(&mut self)
pub fn force_recv_body(&mut self)
Convert the state to receive a body despite method.
Methods like HEAD and CONNECT should not have attached bodies. Some broken APIs use bodies anyway and this is an escape hatch to interoperate with such services.
Source§impl Call<RecvBody>
impl Call<RecvBody>
Sourcepub fn read(
&mut self,
input: &[u8],
output: &mut [u8],
) -> Result<(usize, usize), Error>
pub fn read( &mut self, input: &[u8], output: &mut [u8], ) -> Result<(usize, usize), Error>
Read the response body from input to output.
Depending on response headers, we can be in transfer-encoding: chunked or not. If we are,
there will be less output bytes than input.
The result (usize, usize) is (input consumed, output buffer used).
Sourcepub fn stop_on_chunk_boundary(&mut self, enabled: bool)
pub fn stop_on_chunk_boundary(&mut self, enabled: bool)
Set if we are stopping on chunk boundaries.
If false, we try to fill entire output on each read() call.
Has no meaning unless the response in chunked.
Defaults to false
Sourcepub fn is_on_chunk_boundary(&self) -> bool
pub fn is_on_chunk_boundary(&self) -> bool
Tell if the reading is on a chunk boundary.
Used when we want to read exactly chunk-by-chunk.
Only releveant if we first enabled stop_on_chunk_boundary().
Sourcepub fn can_proceed(&self) -> bool
pub fn can_proceed(&self) -> bool
Check if the response body has been fully received.
Sourcepub fn is_ended_chunked(&self) -> bool
pub fn is_ended_chunked(&self) -> bool
Tell if we got an end chunk when reading chunked.
A normal chunk ending is:
0\r\n
\r\nHowever there are cases where the server abruptly does a FIN after sending 0\r\n.
This means we still got the entire response body, and could use it, but not reuse the connection.
This returns true as soon as we got the 0\r\n.
Sourcepub fn proceed(self) -> Option<RecvBodyResult>
pub fn proceed(self) -> Option<RecvBodyResult>
Proceed to the next state.
Returns None if we are not fully received the body. It is guaranteed that if can_proceed()
returns true, this will return Some.
Source§impl Call<Redirect>
impl Call<Redirect>
Sourcepub fn as_new_call(
&mut self,
redirect_auth_headers: RedirectAuthHeaders,
) -> Result<Option<Call<Prepare>>, Error>
pub fn as_new_call( &mut self, redirect_auth_headers: RedirectAuthHeaders, ) -> Result<Option<Call<Prepare>>, Error>
Construct a new Call by following the redirect.
There are some rules when following a redirect.
- For 307/308
- POST/PUT results in
None, since we do not allow redirecting a request body - DELETE is intentionally excluded: https://stackoverflow.com/questions/299628
- All other methods retain the method in the redirect
- POST/PUT results in
- Other redirect (301, 302, etc)
- HEAD results in HEAD in the redirect
- All other methods becomes GET
Sourcepub fn status(&self) -> StatusCode
pub fn status(&self) -> StatusCode
The redirect status code.
Sourcepub fn must_close_connection(&self) -> bool
pub fn must_close_connection(&self) -> bool
Whether we must close the connection corresponding to the current call.
This is used to inform connection pooling.
Sourcepub fn close_reason(&self) -> Option<&'static str>
pub fn close_reason(&self) -> Option<&'static str>
If we are closing the connection, give a reason why.
Source§impl Call<Cleanup>
impl Call<Cleanup>
Sourcepub fn must_close_connection(&self) -> bool
pub fn must_close_connection(&self) -> bool
Tell if we must close the connection.
Sourcepub fn close_reason(&self) -> Option<&'static str>
pub fn close_reason(&self) -> Option<&'static str>
If we are closing the connection, give a reason.