Struct salvo::http::multipart::Multipart [−][src]
pub struct Multipart<S> where
S: TryStream,
<S as TryStream>::Error: Into<ReadError>, { /* fields omitted */ }
Expand description
The server-side implementation of multipart/form-data
requests.
After constructing with either the ::with_body()
or
::try_from_request()
, two different workflows for processing the
request are provided, assuming any Poll::Pending
and Ready(Err(_))
/Ready(Some(Err(_)))
results are handled in the typical fashion:
High-Level Flow
- Await the next field with
.next_field()
. - Read the field data via the
Stream
impl onField::data
. - Repeat until
.next_field()
returnsNone
.
Low-Level Flow
-
Poll for the first field boundary with
.poll_has_next_field()
; if it returnstrue
proceed to the next step, iffalse
the request is at an end. -
Poll for the field’s headers containing its name, content-type and other info with
.poll_field_headers()
. -
Poll for the field’s data chunks with [
.poll_field_chunk()](#method.poll_field_chunk) until
None` is returned, then loop back to step 2.
Any data before the first boundary and past the end of the terminating boundary is ignored as it is out-of-spec and should not be expected to be left in the underlying stream intact. Please open an issue if you have a legitimate use-case for extraneous data in a multipart request.
Implementations
Construct a new Multipart
with the given body reader and boundary.
The boundary should be taken directly from the Content-Type: multipart/form-data
header
of the request. This will add the requisite --
to the boundary as per
IETF RFC 7578 section 4.1.
pub fn try_from_body_headers(
body: S,
headers: &HeaderMap<HeaderValue>
) -> Result<Multipart<S>, ReadError>
pub fn next_field(&mut self) -> NextField<'_, S>ⓘ where
Multipart<S>: Unpin,
pub fn next_field_pinned(self: Pin<&mut Multipart<S>>) -> NextField<'_, S>ⓘ
pub fn next_field_pinned(self: Pin<&mut Multipart<S>>) -> NextField<'_, S>ⓘ
Same as .next_field()
but with a receiver of Pin<&mut Self>
.
Poll for the next boundary, returning true
if a field should follow that boundary,
or false
if the request is at an end. See above for the overall flow.
If this returns Ready(Ok(true))
, you may then begin
polling for the headers of the next field.
If a field was being read, its contents will be discarded.
This is a low-level call and is expected to be supplemented/replaced by a more ergonomic API once more design work has taken place.
pub fn poll_field_headers(
self: Pin<&mut Multipart<S>>,
cx: &mut Context<'_>
) -> Poll<Result<FieldHeaders, ReadError>>
pub fn poll_field_headers(
self: Pin<&mut Multipart<S>>,
cx: &mut Context<'_>
) -> Poll<Result<FieldHeaders, ReadError>>
Poll for the headers of the next field, returning the headers or an error otherwise.
Once you have the field headers, you may then begin polling for field chunks.
In addition to bubbling up errors from the underlying stream, this will also return an error if:
- the headers were corrupted, or:
- did not contain a
Content-Disposition: form-data
header with aname
parameter, or: - the end of stream was reached before the header segment terminator
\r\n\r\n
, or: - the buffer for the headers exceeds a preset size.
This is a low-level call and is expected to be supplemented/replaced by a more ergonomic API once more design work has taken place.
Note: Calling This Is Not Enforced
If this step is skipped then .poll_field_chunk()
will return chunks of the header segment which may or may not be desirable depending
on your use-case.
If you do want to inspect the raw field headers, they are separated by one CRLF (\r\n
) and
terminated by two CRLFs (\r\n\r\n
) after which the field chunks follow.
Poll for the next chunk of the current field.
This returns Ready(Some(Ok(chunk)))
as long as there are chunks in the field,
yielding Ready(None)
when the next boundary is reached.
You may then begin the next field with
.poll_has_next_field()
.
This is a low-level call and is expected to be supplemented/replaced by a more ergonomic API once more design work has taken place.
Note: Call .poll_field_headers()
First for Correct Data
If .poll_field_headers()
is skipped then this call
will return chunks of the header segment which may or may not be desirable depending
on your use-case.
If you do want to inspect the raw field headers, they are separated by one CRLF (\r\n
) and
terminated by two CRLFs (\r\n\r\n
) after which the field chunks follow.