1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-08-01 18:25:04 +00:00

added content-encoding support to h2

This commit is contained in:
Nikolay Kim 2017-11-06 09:35:52 -08:00
parent bddd8e9c2e
commit 2379bcbf39
3 changed files with 44 additions and 7 deletions

View file

@ -395,6 +395,7 @@ impl Reader {
let payload = if let Some(decoder) = decoder { let payload = if let Some(decoder) = decoder {
let (tx, rx) = Payload::new(false); let (tx, rx) = Payload::new(false);
// Content-Encoding
let enc = if let Some(enc) = msg.headers().get(CONTENT_ENCODING) { let enc = if let Some(enc) = msg.headers().get(CONTENT_ENCODING) {
if let Ok(enc) = enc.to_str() { if let Ok(enc) = enc.to_str() {
ContentEncoding::from(enc) ContentEncoding::from(enc)

View file

@ -7,6 +7,7 @@ use std::collections::VecDeque;
use actix::Arbiter; use actix::Arbiter;
use http::request::Parts; use http::request::Parts;
use http::header::CONTENT_ENCODING;
use http2::{Reason, RecvStream}; use http2::{Reason, RecvStream};
use http2::server::{Server, Handshake, Respond}; use http2::server::{Server, Handshake, Respond};
use bytes::{Buf, Bytes}; use bytes::{Buf, Bytes};
@ -19,7 +20,8 @@ use h2writer::H2Writer;
use channel::HttpHandler; use channel::HttpHandler;
use httpcodes::HTTPNotFound; use httpcodes::HTTPNotFound;
use httprequest::HttpRequest; use httprequest::HttpRequest;
use payload::{Payload, PayloadError, PayloadSender, PayloadWriter}; use httpresponse::ContentEncoding;
use payload::{Payload, PayloadError, PayloadSender, PayloadWriter, EncodedPayload};
const KEEPALIVE_PERIOD: u64 = 15; // seconds const KEEPALIVE_PERIOD: u64 = 15; // seconds
@ -193,10 +195,26 @@ impl<T, A, H> Http2<T, A, H>
} }
} }
struct PayloadInfo(PayloadInfoItem);
enum PayloadInfoItem {
Sender(PayloadSender),
Encoding(EncodedPayload),
}
impl PayloadInfo {
fn as_mut(&mut self) -> &mut PayloadWriter {
match self.0 {
PayloadInfoItem::Sender(ref mut sender) => sender,
PayloadInfoItem::Encoding(ref mut enc) => enc,
}
}
}
struct Entry { struct Entry {
task: Task, task: Task,
req: UnsafeCell<HttpRequest>, req: UnsafeCell<HttpRequest>,
payload: PayloadSender, payload: PayloadInfo,
recv: RecvStream, recv: RecvStream,
stream: H2Writer, stream: H2Writer,
eof: bool, eof: bool,
@ -218,7 +236,23 @@ impl Entry {
let mut req = HttpRequest::new( let mut req = HttpRequest::new(
parts.method, path, parts.version, parts.headers, query); parts.method, path, parts.version, parts.headers, query);
// Payload and Content-Encoding
let (psender, payload) = Payload::new(false); let (psender, payload) = Payload::new(false);
let enc = if let Some(enc) = req.headers().get(CONTENT_ENCODING) {
if let Ok(enc) = enc.to_str() {
ContentEncoding::from(enc)
} else {
ContentEncoding::Auto
}
} else {
ContentEncoding::Auto
};
let psender = match enc {
ContentEncoding::Auto | ContentEncoding::Identity =>
PayloadInfoItem::Sender(psender),
_ => PayloadInfoItem::Encoding(EncodedPayload::new(psender, enc)),
};
// start request processing // start request processing
let mut task = None; let mut task = None;
@ -231,7 +265,7 @@ impl Entry {
Entry {task: task.unwrap_or_else(|| Task::reply(HTTPNotFound)), Entry {task: task.unwrap_or_else(|| Task::reply(HTTPNotFound)),
req: UnsafeCell::new(req), req: UnsafeCell::new(req),
payload: psender, payload: PayloadInfo(psender),
recv: recv, recv: recv,
stream: H2Writer::new(resp), stream: H2Writer::new(resp),
eof: false, eof: false,
@ -246,22 +280,22 @@ impl Entry {
if !self.reof { if !self.reof {
match self.recv.poll() { match self.recv.poll() {
Ok(Async::Ready(Some(chunk))) => { Ok(Async::Ready(Some(chunk))) => {
self.payload.feed_data(chunk); self.payload.as_mut().feed_data(chunk);
}, },
Ok(Async::Ready(None)) => { Ok(Async::Ready(None)) => {
self.reof = true; self.reof = true;
}, },
Ok(Async::NotReady) => (), Ok(Async::NotReady) => (),
Err(err) => { Err(err) => {
self.payload.set_error(PayloadError::Http2(err)) self.payload.as_mut().set_error(PayloadError::Http2(err))
} }
} }
let capacity = self.payload.capacity(); let capacity = self.payload.as_mut().capacity();
if self.capacity != capacity { if self.capacity != capacity {
self.capacity = capacity; self.capacity = capacity;
if let Err(err) = self.recv.release_capacity().release_capacity(capacity) { if let Err(err) = self.recv.release_capacity().release_capacity(capacity) {
self.payload.set_error(PayloadError::Http2(err)) self.payload.as_mut().set_error(PayloadError::Http2(err))
} }
} }
} }

View file

@ -212,6 +212,7 @@ enum Decoder {
Identity, Identity,
} }
// should go after write::GzDecoder get implemented
#[derive(Debug)] #[derive(Debug)]
struct Wrapper { struct Wrapper {
buf: BytesMut buf: BytesMut
@ -247,6 +248,7 @@ impl io::Write for BytesWriter {
} }
// should go after brotli2::write::BrotliDecoder::get_mut get implemented
#[derive(Debug)] #[derive(Debug)]
struct WrapperRc { struct WrapperRc {
buf: Rc<RefCell<BytesMut>>, buf: Rc<RefCell<BytesMut>>,