Skip to content

Commit

Permalink
add protobuf feature
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Mar 9, 2018
1 parent 3f0803a commit f3c63e6
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 83 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 ../..
Expand All @@ -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 "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html &&
cargo install mdbook &&
cd guide && mdbook build -d ../target/doc/guide && cd .. &&
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ alpn = ["openssl", "openssl/v102", "openssl/v110", "tokio-openssl"]
# sessions
session = ["cookie/secure"]

# protobuf
protobuf = ["prost"]

[dependencies]
actix = "^0.5.2"

Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion examples/protobuf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ prost = "0.2.0"
prost-derive = "0.2.0"

actix = "0.5"
actix-web = { path="../../" }
actix-web = { path="../../", features=["protobuf"] }
3 changes: 2 additions & 1 deletion examples/protobuf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extern crate prost;
extern crate prost_derive;

use actix_web::*;
use actix_web::ProtoBufBody;
use futures::Future;


Expand All @@ -22,7 +23,7 @@ pub struct MyObj {

/// This handler uses `HttpRequest::json()` for loading serde json object.
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
req.protobuf()
ProtoBufBody::new(req)
.from_err() // convert all errors into `Error`
.and_then(|val: MyObj| {
println!("model: {:?}", val);
Expand Down
44 changes: 0 additions & 44 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -109,10 +107,6 @@ impl From<failure::Error> 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 {}

Expand Down Expand Up @@ -456,44 +450,6 @@ impl From<JsonError> 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<PayloadError> for ProtoBufPayloadError {
fn from(err: PayloadError) -> ProtoBufPayloadError {
ProtoBufPayloadError::Payload(err)
}
}

impl From<ProtoBufDecodeError> 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)]
Expand Down
8 changes: 0 additions & 8 deletions src/httpmessage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -211,12 +209,6 @@ pub trait HttpMessage {
JsonBody::new(self)
}

fn protobuf<T: Message + Default>(self) -> ProtoBufBody<Self, T>
where Self: Stream<Item=Bytes, Error=PayloadError> + Sized
{
ProtoBufBody::new(self)
}

/// Return stream to http payload processes as multipart.
///
/// Content-type: multipart/form-data;
Expand Down
17 changes: 0 additions & 17 deletions src/httpresponse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -509,22 +508,6 @@ impl HttpResponseBuilder {
Ok(self.body(body)?)
}

pub fn protobuf<T: Message>(&mut self, value: T) -> Result<HttpResponse, Error> {
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.
Expand Down
11 changes: 8 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -112,14 +114,18 @@ mod httprequest;
mod httpresponse;
mod info;
mod json;
mod protobuf;
mod route;
mod router;
mod resource;
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;
Expand All @@ -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;
Expand Down
67 changes: 60 additions & 7 deletions src/protobuf.rs
Original file line number Diff line number Diff line change
@@ -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<PayloadError> for ProtoBufPayloadError {
fn from(err: PayloadError) -> ProtoBufPayloadError {
ProtoBufPayloadError::Payload(err)
}
}

impl From<ProtoBufDecodeError> 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<T: Message>(pub T);
Expand All @@ -32,9 +76,6 @@ impl<T: Message> Responder for ProtoBuf<T> {
}
}




pub struct ProtoBufBody<T, U: Message + Default>{
limit: usize,
ct: &'static str,
Expand Down Expand Up @@ -110,4 +151,16 @@ impl<T, U: Message + Default + 'static> Future for ProtoBufBody<T, U>

self.fut.as_mut().expect("ProtoBufBody could not be used second time").poll()
}
}
}


impl HttpResponseBuilder {

pub fn protobuf<T: Message>(&mut self, value: T) -> Result<HttpResponse, Error> {
self.header(CONTENT_TYPE, "application/protobuf");

let mut body = Vec::new();
value.encode(&mut body)?;
Ok(self.body(body)?)
}
}

0 comments on commit f3c63e6

Please sign in to comment.