1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-10-02 08:12:02 +00:00

allow to set default content encoding on application level

This commit is contained in:
Nikolay Kim 2018-02-18 22:23:17 -08:00
parent 816c6fb0e0
commit edd114f6e4
11 changed files with 73 additions and 21 deletions

View file

@ -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)

View file

@ -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

View file

@ -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<S=()> {
pub(crate) struct Inner<S> {
prefix: usize,
default: Resource<S>,
encoding: ContentEncoding,
router: Router,
resources: Vec<Resource<S>>,
handlers: Vec<(String, Box<RouteHandler<S>>)>,
@ -31,6 +33,10 @@ pub(crate) struct Inner<S> {
impl<S: 'static> PipelineHandler<S> for Inner<S> {
fn encoding(&self) -> ContentEncoding {
self.encoding
}
fn handle(&mut self, mut req: HttpRequest<S>) -> 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<S> {
resources: HashMap<Pattern, Option<Resource<S>>>,
handlers: Vec<(String, Box<RouteHandler<S>>)>,
external: HashMap<String, Pattern>,
encoding: ContentEncoding,
middlewares: Vec<Box<Middleware<S>>>,
}
@ -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<S> Application<S> where S: 'static {
handlers: Vec::new(),
external: HashMap::new(),
middlewares: Vec::new(),
encoding: ContentEncoding::Auto,
})
}
}
@ -253,6 +262,16 @@ impl<S> Application<S> where S: 'static {
self
}
/// Set default content encoding. `ContentEncoding::Auto` is set by default.
pub fn default_encoding<F>(mut self, encoding: ContentEncoding) -> Application<S>
{
{
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<S> Application<S> where S: 'static {
Inner {
prefix: prefix.len(),
default: parts.default,
encoding: parts.encoding,
router: router.clone(),
resources: resources,
handlers: parts.handlers,

View file

@ -162,13 +162,13 @@ impl HttpResponse {
/// Content encoding
#[inline]
pub fn content_encoding(&self) -> ContentEncoding {
pub fn content_encoding(&self) -> Option<ContentEncoding> {
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<bool>,
encoding: ContentEncoding,
encoding: Option<ContentEncoding>,
connection_type: Option<ConnectionType>,
response_size: u64,
error: Option<Error>,
@ -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]

View file

@ -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
//!

View file

@ -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) {

View file

@ -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<S> {
fn encoding(&self) -> ContentEncoding;
fn handle(&mut self, req: HttpRequest<S>) -> Reply;
}
@ -62,6 +66,7 @@ struct PipelineInfo<S> {
context: Option<Box<ActorHttpContext>>,
error: Option<Error>,
disconnected: Option<bool>,
encoding: ContentEncoding,
}
impl<S> PipelineInfo<S> {
@ -73,6 +78,7 @@ impl<S> PipelineInfo<S> {
error: None,
context: None,
disconnected: None,
encoding: ContentEncoding::Auto,
}
}
@ -108,6 +114,7 @@ impl<S: 'static, H: PipelineHandler<S>> Pipeline<S, H> {
error: None,
context: None,
disconnected: None,
encoding: handler.borrow().encoding(),
};
let state = StartMiddlewares::init(&mut info, handler);
@ -451,7 +458,11 @@ impl<S: 'static, H> ProcessResponse<S, H> {
'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());

View file

@ -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) =>

View file

@ -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<T: AsyncWrite> Writer for H1Writer<T> {
self.written
}
fn start(&mut self, req: &mut HttpMessage, msg: &mut HttpResponse) -> io::Result<WriterState> {
fn start(&mut self,
req: &mut HttpMessage,
msg: &mut HttpResponse,
encoding: ContentEncoding) -> io::Result<WriterState>
{
// 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 {

View file

@ -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<WriterState> {
fn start(&mut self, req: &mut HttpMessage, msg: &mut HttpResponse, encoding: ContentEncoding)
-> io::Result<WriterState> {
// 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);
}

View file

@ -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<WriterState>;
fn start(&mut self, req: &mut HttpMessage, resp: &mut HttpResponse, encoding: ContentEncoding)
-> io::Result<WriterState>;
fn write(&mut self, payload: Binary) -> io::Result<WriterState>;