[−][src]Struct salvo::http::multipart::Multipart
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
impl<S> Multipart<S> where
S: TryStream,
<S as TryStream>::Ok: BodyChunk,
<S as TryStream>::Error: Into<ReadError>,
[src]
S: TryStream,
<S as TryStream>::Ok: BodyChunk,
<S as TryStream>::Error: Into<ReadError>,
pub fn with_body<B>(stream: S, boundary: B) -> Multipart<S> where
B: Into<String>,
[src]
B: Into<String>,
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>
[src]
body: S,
headers: &HeaderMap<HeaderValue>
) -> Result<Multipart<S>, ReadError>
pub fn next_field(&mut self) -> NextField<'_, S>ⓘ where
Multipart<S>: Unpin,
[src]
Multipart<S>: Unpin,
pub fn next_field_pinned(self: Pin<&mut Multipart<S>>) -> NextField<'_, S>ⓘ
[src]
Same as .next_field()
but with a receiver of Pin<&mut Self>
.
pub fn poll_has_next_field(
self: Pin<&mut Multipart<S>>,
cx: &mut Context<'_>
) -> Poll<Result<bool, ReadError>>
[src]
self: Pin<&mut Multipart<S>>,
cx: &mut Context<'_>
) -> Poll<Result<bool, ReadError>>
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>>
[src]
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.
pub fn poll_field_chunk(
self: Pin<&mut Multipart<S>>,
cx: &mut Context<'_>
) -> Poll<Option<Result<<S as TryStream>::Ok, ReadError>>>
[src]
self: Pin<&mut Multipart<S>>,
cx: &mut Context<'_>
) -> Poll<Option<Result<<S as TryStream>::Ok, ReadError>>>
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.
Auto Trait Implementations
impl<S> RefUnwindSafe for Multipart<S> where
S: RefUnwindSafe,
<S as TryStream>::Ok: RefUnwindSafe,
[src]
S: RefUnwindSafe,
<S as TryStream>::Ok: RefUnwindSafe,
impl<S> Send for Multipart<S> where
S: Send,
<S as TryStream>::Ok: Send,
[src]
S: Send,
<S as TryStream>::Ok: Send,
impl<S> Sync for Multipart<S> where
S: Sync,
<S as TryStream>::Ok: Sync,
[src]
S: Sync,
<S as TryStream>::Ok: Sync,
impl<S> Unpin for Multipart<S> where
S: Unpin,
<S as TryStream>::Ok: Unpin,
[src]
S: Unpin,
<S as TryStream>::Ok: Unpin,
impl<S> UnwindSafe for Multipart<S> where
S: UnwindSafe,
<S as TryStream>::Ok: UnwindSafe,
[src]
S: UnwindSafe,
<S as TryStream>::Ok: UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T> Instrument for T
[src]
pub fn instrument(self, span: Span) -> Instrumented<Self>
[src]
pub fn in_current_span(self) -> Instrumented<Self>
[src]
impl<T> Instrument for T
[src]
pub fn instrument(self, span: Span) -> Instrumented<Self>
[src]
pub fn in_current_span(self) -> Instrumented<Self>
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> SendSyncUnwindSafe for T where
T: Send + Sync + UnwindSafe + ?Sized,
T: Send + Sync + UnwindSafe + ?Sized,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
pub fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
V: MultiLane<T>,