diff --git a/.travis.yml b/.travis.yml
index 640aa1b92..76e1a8c5d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -59,6 +59,7 @@ script:
cd examples/multipart && cargo check && cd ../..
cd examples/json && cargo check && cd ../..
cd examples/juniper && cargo check && cd ../..
+ cd examples/protobuf && cargo check && cd ../..
cd examples/state && cargo check && cd ../..
cd examples/template_tera && cargo check && cd ../..
cd examples/diesel && cargo check && cd ../..
@@ -77,7 +78,7 @@ script:
after_success:
- |
if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
- cargo doc --features "alpn, tls" --no-deps &&
+ cargo doc --features "alpn, tls, protobuf" --no-deps &&
echo "" > target/doc/index.html &&
cargo install mdbook &&
cd guide && mdbook build -d ../target/doc/guide && cd .. &&
diff --git a/CHANGES.md b/CHANGES.md
index 6a08119ff..8ea018081 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,8 +2,12 @@
## 0.4.6 (2018-03-xx)
+* Add experimental protobuf support
+
* Fix client cookie handling
+* Optimize websockets stream support
+
## 0.4.5 (2018-03-07)
diff --git a/Cargo.toml b/Cargo.toml
index dd22754d7..59dd89f7a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -38,6 +38,9 @@ alpn = ["openssl", "openssl/v102", "openssl/v110", "tokio-openssl"]
# sessions
session = ["cookie/secure"]
+# protobuf
+protobuf = ["prost"]
+
[dependencies]
actix = "^0.5.2"
@@ -60,7 +63,6 @@ rand = "0.4"
regex = "0.2"
serde = "1.0"
serde_json = "1.0"
-prost = "^0.2"
sha1 = "0.6"
smallvec = "0.6"
time = "0.1"
@@ -88,6 +90,9 @@ tokio-tls = { version="0.1", optional = true }
openssl = { version="0.10", optional = true }
tokio-openssl = { version="0.2", optional = true }
+# protobuf
+prost = { version="^0.2", optional = true }
+
[dev-dependencies]
env_logger = "0.5"
skeptic = "0.13"
diff --git a/examples/protobuf/Cargo.toml b/examples/protobuf/Cargo.toml
index 75776ce5a..e5035ec0a 100644
--- a/examples/protobuf/Cargo.toml
+++ b/examples/protobuf/Cargo.toml
@@ -12,4 +12,4 @@ prost = "0.2.0"
prost-derive = "0.2.0"
actix = "0.5"
-actix-web = { path="../../" }
\ No newline at end of file
+actix-web = { path="../../", features=["protobuf"] }
diff --git a/examples/protobuf/src/main.rs b/examples/protobuf/src/main.rs
index ff411fff8..a7fd2cbee 100644
--- a/examples/protobuf/src/main.rs
+++ b/examples/protobuf/src/main.rs
@@ -8,6 +8,7 @@ extern crate prost;
extern crate prost_derive;
use actix_web::*;
+use actix_web::ProtoBufBody;
use futures::Future;
@@ -22,7 +23,7 @@ pub struct MyObj {
/// This handler uses `HttpRequest::json()` for loading serde json object.
fn index(req: HttpRequest) -> Box> {
- req.protobuf()
+ ProtoBufBody::new(req)
.from_err() // convert all errors into `Error`
.and_then(|val: MyObj| {
println!("model: {:?}", val);
diff --git a/src/error.rs b/src/error.rs
index 3c3a088b7..40ecf7045 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -15,8 +15,6 @@ use http::{header, StatusCode, Error as HttpError};
use http::uri::InvalidUriBytes;
use http_range::HttpRangeParseError;
use serde_json::error::Error as JsonError;
-use prost::EncodeError as ProtoBufEncodeError;
-use prost::DecodeError as ProtoBufDecodeError;
pub use url::ParseError as UrlParseError;
// re-exports
@@ -109,10 +107,6 @@ impl From for Error {
/// `InternalServerError` for `JsonError`
impl ResponseError for JsonError {}
-/// `InternalServerError` for `ProtoBufEncodeError` `ProtoBufDecodeError`
-impl ResponseError for ProtoBufEncodeError {}
-impl ResponseError for ProtoBufDecodeError {}
-
/// `InternalServerError` for `UrlParseError`
impl ResponseError for UrlParseError {}
@@ -456,44 +450,6 @@ impl From for JsonPayloadError {
}
}
-#[derive(Fail, Debug)]
-pub enum ProtoBufPayloadError {
- /// Payload size is bigger than 256k
- #[fail(display="Payload size is bigger than 256k")]
- Overflow,
- /// Content type error
- #[fail(display="Content type error")]
- ContentType,
- /// Deserialize error
- #[fail(display="Json deserialize error: {}", _0)]
- Deserialize(#[cause] ProtoBufDecodeError),
- /// Payload error
- #[fail(display="Error that occur during reading payload: {}", _0)]
- Payload(#[cause] PayloadError),
-}
-
-impl ResponseError for ProtoBufPayloadError {
-
- fn error_response(&self) -> HttpResponse {
- match *self {
- ProtoBufPayloadError::Overflow => httpcodes::HttpPayloadTooLarge.into(),
- _ => httpcodes::HttpBadRequest.into(),
- }
- }
-}
-
-impl From for ProtoBufPayloadError {
- fn from(err: PayloadError) -> ProtoBufPayloadError {
- ProtoBufPayloadError::Payload(err)
- }
-}
-
-impl From for ProtoBufPayloadError {
- fn from(err: ProtoBufDecodeError) -> ProtoBufPayloadError {
- ProtoBufPayloadError::Deserialize(err)
- }
-}
-
/// Errors which can occur when attempting to interpret a segment string as a
/// valid path segment.
#[derive(Fail, Debug, PartialEq)]
diff --git a/src/httpmessage.rs b/src/httpmessage.rs
index 61ab3c4da..69065c49c 100644
--- a/src/httpmessage.rs
+++ b/src/httpmessage.rs
@@ -4,7 +4,6 @@ use bytes::{Bytes, BytesMut};
use futures::{Future, Stream, Poll};
use http_range::HttpRange;
use serde::de::DeserializeOwned;
-use prost::Message;
use mime::Mime;
use url::form_urlencoded;
use encoding::all::UTF_8;
@@ -13,7 +12,6 @@ use encoding::label::encoding_from_whatwg_label;
use http::{header, HeaderMap};
use json::JsonBody;
-use protobuf::ProtoBufBody;
use header::Header;
use multipart::Multipart;
use error::{ParseError, ContentTypeError,
@@ -211,12 +209,6 @@ pub trait HttpMessage {
JsonBody::new(self)
}
- fn protobuf(self) -> ProtoBufBody
- where Self: Stream- + Sized
- {
- ProtoBufBody::new(self)
- }
-
/// Return stream to http payload processes as multipart.
///
/// Content-type: multipart/form-data;
diff --git a/src/httpresponse.rs b/src/httpresponse.rs
index 2147a42c1..9c99d4d68 100644
--- a/src/httpresponse.rs
+++ b/src/httpresponse.rs
@@ -11,7 +11,6 @@ use http::{StatusCode, Version, HeaderMap, HttpTryFrom, Error as HttpError};
use http::header::{self, HeaderName, HeaderValue};
use serde_json;
use serde::Serialize;
-use prost::Message;
use body::Body;
use error::Error;
@@ -509,22 +508,6 @@ impl HttpResponseBuilder {
Ok(self.body(body)?)
}
- pub fn protobuf(&mut self, value: T) -> Result {
- let mut body = Vec::new();
- value.encode(&mut body)?;
-
- let contains = if let Some(parts) = parts(&mut self.response, &self.err) {
- parts.headers.contains_key(header::CONTENT_TYPE)
- } else {
- true
- };
- if !contains {
- self.header(header::CONTENT_TYPE, "application/protobuf");
- }
-
- Ok(self.body(body)?)
- }
-
/// Set an empty body and generate `HttpResponse`
///
/// `HttpResponseBuilder` can not be used after this call.
diff --git a/src/lib.rs b/src/lib.rs
index 39e1e48a9..8c021ca99 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -78,7 +78,6 @@ extern crate url;
extern crate libc;
extern crate serde;
extern crate serde_json;
-extern crate prost;
extern crate flate2;
extern crate brotli2;
extern crate encoding;
@@ -89,6 +88,9 @@ extern crate h2 as http2;
extern crate trust_dns_resolver;
#[macro_use] extern crate actix;
+#[cfg(feature="protobuf")]
+extern crate prost;
+
#[cfg(test)]
#[macro_use] extern crate serde_derive;
@@ -112,7 +114,6 @@ mod httprequest;
mod httpresponse;
mod info;
mod json;
-mod protobuf;
mod route;
mod router;
mod resource;
@@ -120,6 +121,11 @@ mod param;
mod payload;
mod pipeline;
+#[cfg(feature="protobuf")]
+mod protobuf;
+#[cfg(feature="protobuf")]
+pub use protobuf::{ProtoBuf, ProtoBufBody};
+
pub mod client;
pub mod fs;
pub mod ws;
@@ -134,7 +140,6 @@ pub mod server;
pub use error::{Error, Result, ResponseError};
pub use body::{Body, Binary};
pub use json::Json;
-pub use protobuf::ProtoBuf;
pub use application::Application;
pub use httpmessage::HttpMessage;
pub use httprequest::HttpRequest;
diff --git a/src/protobuf.rs b/src/protobuf.rs
index 439f26179..e0147a1de 100644
--- a/src/protobuf.rs
+++ b/src/protobuf.rs
@@ -1,16 +1,60 @@
use bytes::{Bytes, BytesMut};
use futures::{Poll, Future, Stream};
-use http::header::CONTENT_LENGTH;
+use http::header::{CONTENT_TYPE, CONTENT_LENGTH};
use bytes::IntoBuf;
use prost::Message;
+use prost::EncodeError as ProtoBufEncodeError;
+use prost::DecodeError as ProtoBufDecodeError;
-use error::{Error, ProtoBufPayloadError, PayloadError};
+use error::{Error, PayloadError, ResponseError};
use handler::Responder;
use httpmessage::HttpMessage;
use httprequest::HttpRequest;
-use httpresponse::HttpResponse;
+use httpresponse::{HttpResponse, HttpResponseBuilder};
+use httpcodes::{HttpBadRequest, HttpPayloadTooLarge};
+#[derive(Fail, Debug)]
+pub enum ProtoBufPayloadError {
+ /// Payload size is bigger than 256k
+ #[fail(display="Payload size is bigger than 256k")]
+ Overflow,
+ /// Content type error
+ #[fail(display="Content type error")]
+ ContentType,
+ /// Deserialize error
+ #[fail(display="Json deserialize error: {}", _0)]
+ Deserialize(#[cause] ProtoBufDecodeError),
+ /// Payload error
+ #[fail(display="Error that occur during reading payload: {}", _0)]
+ Payload(#[cause] PayloadError),
+}
+
+impl ResponseError for ProtoBufPayloadError {
+
+ fn error_response(&self) -> HttpResponse {
+ match *self {
+ ProtoBufPayloadError::Overflow => HttpPayloadTooLarge.into(),
+ _ => HttpBadRequest.into(),
+ }
+ }
+}
+
+impl From for ProtoBufPayloadError {
+ fn from(err: PayloadError) -> ProtoBufPayloadError {
+ ProtoBufPayloadError::Payload(err)
+ }
+}
+
+impl From for ProtoBufPayloadError {
+ fn from(err: ProtoBufDecodeError) -> ProtoBufPayloadError {
+ ProtoBufPayloadError::Deserialize(err)
+ }
+}
+
+/// `InternalServerError` for `ProtoBufEncodeError` `ProtoBufDecodeError`
+impl ResponseError for ProtoBufEncodeError {}
+impl ResponseError for ProtoBufDecodeError {}
#[derive(Debug)]
pub struct ProtoBuf(pub T);
@@ -32,9 +76,6 @@ impl Responder for ProtoBuf {
}
}
-
-
-
pub struct ProtoBufBody{
limit: usize,
ct: &'static str,
@@ -110,4 +151,16 @@ impl Future for ProtoBufBody
self.fut.as_mut().expect("ProtoBufBody could not be used second time").poll()
}
-}
\ No newline at end of file
+}
+
+
+impl HttpResponseBuilder {
+
+ pub fn protobuf(&mut self, value: T) -> Result {
+ self.header(CONTENT_TYPE, "application/protobuf");
+
+ let mut body = Vec::new();
+ value.encode(&mut body)?;
+ Ok(self.body(body)?)
+ }
+}