feat(client): add method to end a chunked body for a Request
Closes #831
This commit is contained in:
@@ -646,13 +646,6 @@ impl<H: MessageHandler<T>, T: Transport> State<H, T> {
|
||||
_ => Reading::Closed,
|
||||
};
|
||||
let writing = match http1.writing {
|
||||
Writing::Ready(ref encoder) if encoder.is_eof() => {
|
||||
if http1.keep_alive {
|
||||
Writing::KeepAlive
|
||||
} else {
|
||||
Writing::Closed
|
||||
}
|
||||
},
|
||||
Writing::Ready(encoder) => {
|
||||
if encoder.is_eof() {
|
||||
if http1.keep_alive {
|
||||
@@ -660,7 +653,7 @@ impl<H: MessageHandler<T>, T: Transport> State<H, T> {
|
||||
} else {
|
||||
Writing::Closed
|
||||
}
|
||||
} else if let Some(buf) = encoder.end() {
|
||||
} else if let Some(buf) = encoder.finish() {
|
||||
Writing::Chunk(Chunk {
|
||||
buf: buf.bytes,
|
||||
pos: buf.pos,
|
||||
@@ -680,7 +673,7 @@ impl<H: MessageHandler<T>, T: Transport> State<H, T> {
|
||||
} else {
|
||||
Writing::Closed
|
||||
}
|
||||
} else if let Some(buf) = encoder.end() {
|
||||
} else if let Some(buf) = encoder.finish() {
|
||||
Writing::Chunk(Chunk {
|
||||
buf: buf.bytes,
|
||||
pos: buf.pos,
|
||||
@@ -719,14 +712,26 @@ impl<H: MessageHandler<T>, T: Transport> State<H, T> {
|
||||
};
|
||||
|
||||
http1.writing = match http1.writing {
|
||||
Writing::Ready(encoder) => if encoder.is_eof() {
|
||||
if http1.keep_alive {
|
||||
Writing::KeepAlive
|
||||
Writing::Ready(encoder) => {
|
||||
if encoder.is_eof() {
|
||||
if http1.keep_alive {
|
||||
Writing::KeepAlive
|
||||
} else {
|
||||
Writing::Closed
|
||||
}
|
||||
} else if encoder.is_closed() {
|
||||
if let Some(buf) = encoder.finish() {
|
||||
Writing::Chunk(Chunk {
|
||||
buf: buf.bytes,
|
||||
pos: buf.pos,
|
||||
next: (h1::Encoder::length(0), Next::wait())
|
||||
})
|
||||
} else {
|
||||
Writing::Closed
|
||||
}
|
||||
} else {
|
||||
Writing::Closed
|
||||
Writing::Wait(encoder)
|
||||
}
|
||||
} else {
|
||||
Writing::Wait(encoder)
|
||||
},
|
||||
Writing::Chunk(chunk) => if chunk.is_written() {
|
||||
Writing::Wait(chunk.next.0)
|
||||
|
||||
@@ -8,7 +8,8 @@ use http::internal::{AtomicWrite, WriteBuf};
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Encoder {
|
||||
kind: Kind,
|
||||
prefix: Prefix, //Option<WriteBuf<Vec<u8>>>
|
||||
prefix: Prefix,
|
||||
is_closed: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
@@ -25,14 +26,16 @@ impl Encoder {
|
||||
pub fn chunked() -> Encoder {
|
||||
Encoder {
|
||||
kind: Kind::Chunked(Chunked::Init),
|
||||
prefix: Prefix(None)
|
||||
prefix: Prefix(None),
|
||||
is_closed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn length(len: u64) -> Encoder {
|
||||
Encoder {
|
||||
kind: Kind::Length(len),
|
||||
prefix: Prefix(None)
|
||||
prefix: Prefix(None),
|
||||
is_closed: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +54,16 @@ impl Encoder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(self) -> Option<WriteBuf<Cow<'static, [u8]>>> {
|
||||
/// User has called `encoder.close()` in a `Handler`.
|
||||
pub fn is_closed(&self) -> bool {
|
||||
self.is_closed
|
||||
}
|
||||
|
||||
pub fn close(&mut self) {
|
||||
self.is_closed = true;
|
||||
}
|
||||
|
||||
pub fn finish(self) -> Option<WriteBuf<Cow<'static, [u8]>>> {
|
||||
let trailer = self.trailer();
|
||||
let buf = self.prefix.0;
|
||||
|
||||
@@ -335,7 +347,7 @@ mod tests {
|
||||
use mock::{Async, Buf};
|
||||
|
||||
#[test]
|
||||
fn test_write_chunked_sync() {
|
||||
fn test_chunked_encode_sync() {
|
||||
let mut dst = Buf::new();
|
||||
let mut encoder = Encoder::chunked();
|
||||
|
||||
@@ -346,7 +358,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_chunked_async() {
|
||||
fn test_chunked_encode_async() {
|
||||
let mut dst = Async::new(Buf::new(), 7);
|
||||
let mut encoder = Encoder::chunked();
|
||||
|
||||
@@ -360,7 +372,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_sized() {
|
||||
fn test_sized_encode() {
|
||||
let mut dst = Buf::new();
|
||||
let mut encoder = Encoder::length(8);
|
||||
encoder.encode(&mut dst, b"foo bar").unwrap();
|
||||
|
||||
@@ -72,6 +72,7 @@ impl<'a, T: Read> Decoder<'a, T> {
|
||||
Decoder(DecoderImpl::H1(decoder, transport))
|
||||
}
|
||||
|
||||
|
||||
/// Get a reference to the transport.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
match self.0 {
|
||||
@@ -85,6 +86,17 @@ impl<'a, T: Transport> Encoder<'a, T> {
|
||||
Encoder(EncoderImpl::H1(encoder, transport))
|
||||
}
|
||||
|
||||
/// Closes an encoder, signaling that no more writing will occur.
|
||||
///
|
||||
/// This is needed for encodings that don't know length of the content
|
||||
/// beforehand. Most common instance would be usage of
|
||||
/// `Transfer-Enciding: chunked`. You would call `close()` to signal
|
||||
/// the `Encoder` should write the end chunk, or `0\r\n\r\n`.
|
||||
pub fn close(&mut self) {
|
||||
match self.0 {
|
||||
EncoderImpl::H1(ref mut encoder, _) => encoder.close()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the transport.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
@@ -113,7 +125,11 @@ impl<'a, T: Transport> Write for Encoder<'a, T> {
|
||||
}
|
||||
match self.0 {
|
||||
EncoderImpl::H1(ref mut encoder, ref mut transport) => {
|
||||
encoder.encode(*transport, data)
|
||||
if encoder.is_closed() {
|
||||
Ok(0)
|
||||
} else {
|
||||
encoder.encode(*transport, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user