mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
allow to set default content encoding on application level
This commit is contained in:
parent
816c6fb0e0
commit
edd114f6e4
12
CHANGES.md
12
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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
//!
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
@ -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) =>
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user