From edd114f6e46c8c8dc8c4c90d3a197fe8f59aa2a7 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 18 Feb 2018 22:23:17 -0800 Subject: [PATCH] allow to set default content encoding on application level --- CHANGES.md | 12 +++++++++++- guide/src/qs_1.md | 2 +- src/application.rs | 20 ++++++++++++++++++++ src/httpresponse.rs | 16 ++++++++-------- src/lib.rs | 4 ++-- src/middleware/cors.rs | 1 - src/pipeline.rs | 13 ++++++++++++- src/server/encoding.rs | 7 +++++-- src/server/h1writer.rs | 9 +++++++-- src/server/h2writer.rs | 6 ++++-- src/server/mod.rs | 4 +++- 11 files changed, 73 insertions(+), 21 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index acf8ddf32..d688c4e93 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,15 +1,25 @@ # Changes -## 0.3.4 (2018-..-..) +## 0.4.0 (2018-02-..) + +* Actix 0.5 compatibility * Fix request json loader +* Simplify HttpServer type definition + * Added HttpRequest::mime_type() method +* Added HttpRequest::uri_mut(), allows to modify request uri + * Added StaticFiles::index_file() * Added basic websocket client +* Added TestServer::ws(), test websockets client + +* Allow to override content encoding on application level + ## 0.3.3 (2018-01-25) diff --git a/guide/src/qs_1.md b/guide/src/qs_1.md index c9fbc8f35..26c01784b 100644 --- a/guide/src/qs_1.md +++ b/guide/src/qs_1.md @@ -17,7 +17,7 @@ If you already have rustup installed, run this command to ensure you have the la rustup update ``` -Actix web framework requires rust version 1.20 and up. +Actix web framework requires rust version 1.21 and up. ## Running Examples diff --git a/src/application.rs b/src/application.rs index 047364b85..a4df14397 100644 --- a/src/application.rs +++ b/src/application.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use handler::Reply; use router::{Router, Pattern}; use resource::Resource; +use headers::ContentEncoding; use handler::{Handler, RouteHandler, WrapHandler}; use httprequest::HttpRequest; use pipeline::{Pipeline, PipelineHandler}; @@ -24,6 +25,7 @@ pub struct HttpApplication { pub(crate) struct Inner { prefix: usize, default: Resource, + encoding: ContentEncoding, router: Router, resources: Vec>, handlers: Vec<(String, Box>)>, @@ -31,6 +33,10 @@ pub(crate) struct Inner { impl PipelineHandler for Inner { + fn encoding(&self) -> ContentEncoding { + self.encoding + } + fn handle(&mut self, mut req: HttpRequest) -> Reply { if let Some(idx) = self.router.recognize(&mut req) { self.resources[idx].handle(req.clone(), Some(&mut self.default)) @@ -97,6 +103,7 @@ struct ApplicationParts { resources: HashMap>>, handlers: Vec<(String, Box>)>, external: HashMap, + encoding: ContentEncoding, middlewares: Vec>>, } @@ -119,6 +126,7 @@ impl Application<()> { resources: HashMap::new(), handlers: Vec::new(), external: HashMap::new(), + encoding: ContentEncoding::Auto, middlewares: Vec::new(), }) } @@ -149,6 +157,7 @@ impl Application where S: 'static { handlers: Vec::new(), external: HashMap::new(), middlewares: Vec::new(), + encoding: ContentEncoding::Auto, }) } } @@ -253,6 +262,16 @@ impl Application where S: 'static { self } + /// Set default content encoding. `ContentEncoding::Auto` is set by default. + pub fn default_encoding(mut self, encoding: ContentEncoding) -> Application + { + { + let parts = self.parts.as_mut().expect("Use after finish"); + parts.encoding = encoding; + } + self + } + /// Register external resource. /// /// External resources are useful for URL generation purposes only and @@ -344,6 +363,7 @@ impl Application where S: 'static { Inner { prefix: prefix.len(), default: parts.default, + encoding: parts.encoding, router: router.clone(), resources: resources, handlers: parts.handlers, diff --git a/src/httpresponse.rs b/src/httpresponse.rs index ebcaefe9d..77b63f125 100644 --- a/src/httpresponse.rs +++ b/src/httpresponse.rs @@ -162,13 +162,13 @@ impl HttpResponse { /// Content encoding #[inline] - pub fn content_encoding(&self) -> ContentEncoding { + pub fn content_encoding(&self) -> Option { self.get_ref().encoding } /// Set content encoding pub fn set_content_encoding(&mut self, enc: ContentEncoding) -> &mut Self { - self.get_mut().encoding = enc; + self.get_mut().encoding = Some(enc); self } @@ -294,7 +294,7 @@ impl HttpResponseBuilder { #[inline] pub fn content_encoding(&mut self, enc: ContentEncoding) -> &mut Self { if let Some(parts) = parts(&mut self.response, &self.err) { - parts.encoding = enc; + parts.encoding = Some(enc); } self } @@ -648,7 +648,7 @@ struct InnerHttpResponse { reason: Option<&'static str>, body: Body, chunked: Option, - encoding: ContentEncoding, + encoding: Option, connection_type: Option, response_size: u64, error: Option, @@ -665,7 +665,7 @@ impl InnerHttpResponse { reason: None, body: body, chunked: None, - encoding: ContentEncoding::Auto, + encoding: None, connection_type: None, response_size: 0, error: None, @@ -717,7 +717,7 @@ impl Pool { inner.version = None; inner.chunked = None; inner.reason = None; - inner.encoding = ContentEncoding::Auto; + inner.encoding = None; inner.connection_type = None; inner.response_size = 0; inner.error = None; @@ -809,11 +809,11 @@ mod tests { #[test] fn test_content_encoding() { let resp = HttpResponse::build(StatusCode::OK).finish().unwrap(); - assert_eq!(resp.content_encoding(), ContentEncoding::Auto); + assert_eq!(resp.content_encoding(), None); let resp = HttpResponse::build(StatusCode::OK) .content_encoding(ContentEncoding::Br).finish().unwrap(); - assert_eq!(resp.content_encoding(), ContentEncoding::Br); + assert_eq!(resp.content_encoding(), Some(ContentEncoding::Br)); } #[test] diff --git a/src/lib.rs b/src/lib.rs index 7a6dcd377..c9819aef3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,8 +24,8 @@ //! * [User Guide](http://actix.github.io/actix-web/guide/) //! * [Chat on gitter](https://gitter.im/actix/actix) //! * [GitHub repository](https://github.com/actix/actix-web) -//! * Cargo package: [actix-web](https://crates.io/crates/actix-web) -//! * Supported Rust version: 1.20 or later +//! * [Cargo package](https://crates.io/crates/actix-web) +//! * Supported Rust version: 1.21 or later //! //! ## Features //! diff --git a/src/middleware/cors.rs b/src/middleware/cors.rs index d80cbd4f7..748ab1bba 100644 --- a/src/middleware/cors.rs +++ b/src/middleware/cors.rs @@ -441,7 +441,6 @@ impl CorsBuilder { /// [Resource Processing Model](https://www.w3.org/TR/cors/#resource-processing-model). /// /// Defaults to `All`. - /// ``` pub fn allowed_origin(&mut self, origin: &str) -> &mut CorsBuilder { if let Some(cors) = cors(&mut self.cors, &self.error) { match Uri::try_from(origin) { diff --git a/src/pipeline.rs b/src/pipeline.rs index f7282552b..83714e09a 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -10,6 +10,7 @@ use futures::unsync::oneshot; use body::{Body, BodyStream}; use context::{Frame, ActorHttpContext}; use error::Error; +use headers::ContentEncoding; use handler::{Reply, ReplyItem}; use httprequest::HttpRequest; use httpresponse::HttpResponse; @@ -18,6 +19,9 @@ use application::Inner; use server::{Writer, WriterState, HttpHandlerTask}; pub(crate) trait PipelineHandler { + + fn encoding(&self) -> ContentEncoding; + fn handle(&mut self, req: HttpRequest) -> Reply; } @@ -62,6 +66,7 @@ struct PipelineInfo { context: Option>, error: Option, disconnected: Option, + encoding: ContentEncoding, } impl PipelineInfo { @@ -73,6 +78,7 @@ impl PipelineInfo { error: None, context: None, disconnected: None, + encoding: ContentEncoding::Auto, } } @@ -108,6 +114,7 @@ impl> Pipeline { error: None, context: None, disconnected: None, + encoding: handler.borrow().encoding(), }; let state = StartMiddlewares::init(&mut info, handler); @@ -451,7 +458,11 @@ impl ProcessResponse { 'outter: loop { let result = match mem::replace(&mut self.iostate, IOState::Done) { IOState::Response => { - let result = match io.start(info.req_mut().get_inner(), &mut self.resp) { + let encoding = self.resp.content_encoding().unwrap_or(info.encoding); + + let result = match io.start(info.req_mut().get_inner(), + &mut self.resp, encoding) + { Ok(res) => res, Err(err) => { info.error = Some(err.into()); diff --git a/src/server/encoding.rs b/src/server/encoding.rs index bf872a499..125a9e523 100644 --- a/src/server/encoding.rs +++ b/src/server/encoding.rs @@ -347,10 +347,13 @@ impl PayloadEncoder { PayloadEncoder(ContentEncoder::Identity(TransferEncoding::eof(bytes))) } - pub fn new(buf: SharedBytes, req: &HttpMessage, resp: &mut HttpResponse) -> PayloadEncoder { + pub fn new(buf: SharedBytes, + req: &HttpMessage, + resp: &mut HttpResponse, + response_encoding: ContentEncoding) -> PayloadEncoder + { let version = resp.version().unwrap_or_else(|| req.version); let mut body = resp.replace_body(Body::Empty); - let response_encoding = resp.content_encoding(); let has_body = match body { Body::Empty => false, Body::Binary(ref bin) => diff --git a/src/server/h1writer.rs b/src/server/h1writer.rs index 9bf99a624..165f28e0c 100644 --- a/src/server/h1writer.rs +++ b/src/server/h1writer.rs @@ -7,6 +7,7 @@ use http::header::{HeaderValue, CONNECTION, DATE}; use helpers; use body::{Body, Binary}; +use headers::ContentEncoding; use httprequest::HttpMessage; use httpresponse::HttpResponse; use super::{Writer, WriterState, MAX_WRITE_BUFFER_SIZE}; @@ -94,9 +95,13 @@ impl Writer for H1Writer { self.written } - fn start(&mut self, req: &mut HttpMessage, msg: &mut HttpResponse) -> io::Result { + fn start(&mut self, + req: &mut HttpMessage, + msg: &mut HttpResponse, + encoding: ContentEncoding) -> io::Result + { // prepare task - self.encoder = PayloadEncoder::new(self.buffer.clone(), req, msg); + self.encoder = PayloadEncoder::new(self.buffer.clone(), req, msg, encoding); if msg.keep_alive().unwrap_or_else(|| req.keep_alive()) { self.flags.insert(Flags::STARTED | Flags::KEEPALIVE); } else { diff --git a/src/server/h2writer.rs b/src/server/h2writer.rs index 7ce05a629..00a981915 100644 --- a/src/server/h2writer.rs +++ b/src/server/h2writer.rs @@ -8,6 +8,7 @@ use http::header::{HeaderValue, CONNECTION, TRANSFER_ENCODING, DATE, CONTENT_LEN use helpers; use body::{Body, Binary}; +use headers::ContentEncoding; use httprequest::HttpMessage; use httpresponse::HttpResponse; use super::encoding::PayloadEncoder; @@ -108,10 +109,11 @@ impl Writer for H2Writer { self.written } - fn start(&mut self, req: &mut HttpMessage, msg: &mut HttpResponse) -> io::Result { + fn start(&mut self, req: &mut HttpMessage, msg: &mut HttpResponse, encoding: ContentEncoding) + -> io::Result { // prepare response self.flags.insert(Flags::STARTED); - self.encoder = PayloadEncoder::new(self.buffer.clone(), req, msg); + self.encoder = PayloadEncoder::new(self.buffer.clone(), req, msg, encoding); if let Body::Empty = *msg.body() { self.flags.insert(Flags::EOF); } diff --git a/src/server/mod.rs b/src/server/mod.rs index 1a7b846b6..3769e588e 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -24,6 +24,7 @@ pub use self::settings::ServerSettings; use body::Binary; use error::Error; +use headers::ContentEncoding; use httprequest::{HttpMessage, HttpRequest}; use httpresponse::HttpResponse; @@ -102,7 +103,8 @@ pub enum WriterState { pub trait Writer { fn written(&self) -> u64; - fn start(&mut self, req: &mut HttpMessage, resp: &mut HttpResponse) -> io::Result; + fn start(&mut self, req: &mut HttpMessage, resp: &mut HttpResponse, encoding: ContentEncoding) + -> io::Result; fn write(&mut self, payload: Binary) -> io::Result;