mirror of
https://github.com/actix/actix-extras.git
synced 2025-02-25 19:42:48 +01:00
add protobuf feature
This commit is contained in:
parent
3f0803a7d3
commit
f3c63e631a
@ -59,6 +59,7 @@ script:
|
|||||||
cd examples/multipart && cargo check && cd ../..
|
cd examples/multipart && cargo check && cd ../..
|
||||||
cd examples/json && cargo check && cd ../..
|
cd examples/json && cargo check && cd ../..
|
||||||
cd examples/juniper && cargo check && cd ../..
|
cd examples/juniper && cargo check && cd ../..
|
||||||
|
cd examples/protobuf && cargo check && cd ../..
|
||||||
cd examples/state && cargo check && cd ../..
|
cd examples/state && cargo check && cd ../..
|
||||||
cd examples/template_tera && cargo check && cd ../..
|
cd examples/template_tera && cargo check && cd ../..
|
||||||
cd examples/diesel && cargo check && cd ../..
|
cd examples/diesel && cargo check && cd ../..
|
||||||
@ -77,7 +78,7 @@ script:
|
|||||||
after_success:
|
after_success:
|
||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
|
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 &&
|
echo "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html &&
|
||||||
cargo install mdbook &&
|
cargo install mdbook &&
|
||||||
cd guide && mdbook build -d ../target/doc/guide && cd .. &&
|
cd guide && mdbook build -d ../target/doc/guide && cd .. &&
|
||||||
|
@ -2,8 +2,12 @@
|
|||||||
|
|
||||||
## 0.4.6 (2018-03-xx)
|
## 0.4.6 (2018-03-xx)
|
||||||
|
|
||||||
|
* Add experimental protobuf support
|
||||||
|
|
||||||
* Fix client cookie handling
|
* Fix client cookie handling
|
||||||
|
|
||||||
|
* Optimize websockets stream support
|
||||||
|
|
||||||
|
|
||||||
## 0.4.5 (2018-03-07)
|
## 0.4.5 (2018-03-07)
|
||||||
|
|
||||||
|
@ -38,6 +38,9 @@ alpn = ["openssl", "openssl/v102", "openssl/v110", "tokio-openssl"]
|
|||||||
# sessions
|
# sessions
|
||||||
session = ["cookie/secure"]
|
session = ["cookie/secure"]
|
||||||
|
|
||||||
|
# protobuf
|
||||||
|
protobuf = ["prost"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "^0.5.2"
|
actix = "^0.5.2"
|
||||||
|
|
||||||
@ -60,7 +63,6 @@ rand = "0.4"
|
|||||||
regex = "0.2"
|
regex = "0.2"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
prost = "^0.2"
|
|
||||||
sha1 = "0.6"
|
sha1 = "0.6"
|
||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
@ -88,6 +90,9 @@ tokio-tls = { version="0.1", optional = true }
|
|||||||
openssl = { version="0.10", optional = true }
|
openssl = { version="0.10", optional = true }
|
||||||
tokio-openssl = { version="0.2", optional = true }
|
tokio-openssl = { version="0.2", optional = true }
|
||||||
|
|
||||||
|
# protobuf
|
||||||
|
prost = { version="^0.2", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
skeptic = "0.13"
|
skeptic = "0.13"
|
||||||
|
@ -12,4 +12,4 @@ prost = "0.2.0"
|
|||||||
prost-derive = "0.2.0"
|
prost-derive = "0.2.0"
|
||||||
|
|
||||||
actix = "0.5"
|
actix = "0.5"
|
||||||
actix-web = { path="../../" }
|
actix-web = { path="../../", features=["protobuf"] }
|
||||||
|
@ -8,6 +8,7 @@ extern crate prost;
|
|||||||
extern crate prost_derive;
|
extern crate prost_derive;
|
||||||
|
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
|
use actix_web::ProtoBufBody;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ pub struct MyObj {
|
|||||||
|
|
||||||
/// This handler uses `HttpRequest::json()` for loading serde json object.
|
/// This handler uses `HttpRequest::json()` for loading serde json object.
|
||||||
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
||||||
req.protobuf()
|
ProtoBufBody::new(req)
|
||||||
.from_err() // convert all errors into `Error`
|
.from_err() // convert all errors into `Error`
|
||||||
.and_then(|val: MyObj| {
|
.and_then(|val: MyObj| {
|
||||||
println!("model: {:?}", val);
|
println!("model: {:?}", val);
|
||||||
|
44
src/error.rs
44
src/error.rs
@ -15,8 +15,6 @@ use http::{header, StatusCode, Error as HttpError};
|
|||||||
use http::uri::InvalidUriBytes;
|
use http::uri::InvalidUriBytes;
|
||||||
use http_range::HttpRangeParseError;
|
use http_range::HttpRangeParseError;
|
||||||
use serde_json::error::Error as JsonError;
|
use serde_json::error::Error as JsonError;
|
||||||
use prost::EncodeError as ProtoBufEncodeError;
|
|
||||||
use prost::DecodeError as ProtoBufDecodeError;
|
|
||||||
pub use url::ParseError as UrlParseError;
|
pub use url::ParseError as UrlParseError;
|
||||||
|
|
||||||
// re-exports
|
// re-exports
|
||||||
@ -109,10 +107,6 @@ impl From<failure::Error> for Error {
|
|||||||
/// `InternalServerError` for `JsonError`
|
/// `InternalServerError` for `JsonError`
|
||||||
impl ResponseError for JsonError {}
|
impl ResponseError for JsonError {}
|
||||||
|
|
||||||
/// `InternalServerError` for `ProtoBufEncodeError` `ProtoBufDecodeError`
|
|
||||||
impl ResponseError for ProtoBufEncodeError {}
|
|
||||||
impl ResponseError for ProtoBufDecodeError {}
|
|
||||||
|
|
||||||
/// `InternalServerError` for `UrlParseError`
|
/// `InternalServerError` for `UrlParseError`
|
||||||
impl ResponseError for UrlParseError {}
|
impl ResponseError for UrlParseError {}
|
||||||
|
|
||||||
@ -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
|
/// Errors which can occur when attempting to interpret a segment string as a
|
||||||
/// valid path segment.
|
/// valid path segment.
|
||||||
#[derive(Fail, Debug, PartialEq)]
|
#[derive(Fail, Debug, PartialEq)]
|
||||||
|
@ -4,7 +4,6 @@ use bytes::{Bytes, BytesMut};
|
|||||||
use futures::{Future, Stream, Poll};
|
use futures::{Future, Stream, Poll};
|
||||||
use http_range::HttpRange;
|
use http_range::HttpRange;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use prost::Message;
|
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use url::form_urlencoded;
|
use url::form_urlencoded;
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
@ -13,7 +12,6 @@ use encoding::label::encoding_from_whatwg_label;
|
|||||||
use http::{header, HeaderMap};
|
use http::{header, HeaderMap};
|
||||||
|
|
||||||
use json::JsonBody;
|
use json::JsonBody;
|
||||||
use protobuf::ProtoBufBody;
|
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use multipart::Multipart;
|
use multipart::Multipart;
|
||||||
use error::{ParseError, ContentTypeError,
|
use error::{ParseError, ContentTypeError,
|
||||||
@ -211,12 +209,6 @@ pub trait HttpMessage {
|
|||||||
JsonBody::new(self)
|
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.
|
/// Return stream to http payload processes as multipart.
|
||||||
///
|
///
|
||||||
/// Content-type: multipart/form-data;
|
/// Content-type: multipart/form-data;
|
||||||
|
@ -11,7 +11,6 @@ use http::{StatusCode, Version, HeaderMap, HttpTryFrom, Error as HttpError};
|
|||||||
use http::header::{self, HeaderName, HeaderValue};
|
use http::header::{self, HeaderName, HeaderValue};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use prost::Message;
|
|
||||||
|
|
||||||
use body::Body;
|
use body::Body;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
@ -509,22 +508,6 @@ impl HttpResponseBuilder {
|
|||||||
Ok(self.body(body)?)
|
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`
|
/// Set an empty body and generate `HttpResponse`
|
||||||
///
|
///
|
||||||
/// `HttpResponseBuilder` can not be used after this call.
|
/// `HttpResponseBuilder` can not be used after this call.
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -78,7 +78,6 @@ extern crate url;
|
|||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate prost;
|
|
||||||
extern crate flate2;
|
extern crate flate2;
|
||||||
extern crate brotli2;
|
extern crate brotli2;
|
||||||
extern crate encoding;
|
extern crate encoding;
|
||||||
@ -89,6 +88,9 @@ extern crate h2 as http2;
|
|||||||
extern crate trust_dns_resolver;
|
extern crate trust_dns_resolver;
|
||||||
#[macro_use] extern crate actix;
|
#[macro_use] extern crate actix;
|
||||||
|
|
||||||
|
#[cfg(feature="protobuf")]
|
||||||
|
extern crate prost;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use] extern crate serde_derive;
|
||||||
|
|
||||||
@ -112,7 +114,6 @@ mod httprequest;
|
|||||||
mod httpresponse;
|
mod httpresponse;
|
||||||
mod info;
|
mod info;
|
||||||
mod json;
|
mod json;
|
||||||
mod protobuf;
|
|
||||||
mod route;
|
mod route;
|
||||||
mod router;
|
mod router;
|
||||||
mod resource;
|
mod resource;
|
||||||
@ -120,6 +121,11 @@ mod param;
|
|||||||
mod payload;
|
mod payload;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
|
|
||||||
|
#[cfg(feature="protobuf")]
|
||||||
|
mod protobuf;
|
||||||
|
#[cfg(feature="protobuf")]
|
||||||
|
pub use protobuf::{ProtoBuf, ProtoBufBody};
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
@ -134,7 +140,6 @@ pub mod server;
|
|||||||
pub use error::{Error, Result, ResponseError};
|
pub use error::{Error, Result, ResponseError};
|
||||||
pub use body::{Body, Binary};
|
pub use body::{Body, Binary};
|
||||||
pub use json::Json;
|
pub use json::Json;
|
||||||
pub use protobuf::ProtoBuf;
|
|
||||||
pub use application::Application;
|
pub use application::Application;
|
||||||
pub use httpmessage::HttpMessage;
|
pub use httpmessage::HttpMessage;
|
||||||
pub use httprequest::HttpRequest;
|
pub use httprequest::HttpRequest;
|
||||||
|
@ -1,16 +1,60 @@
|
|||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::{Poll, Future, Stream};
|
use futures::{Poll, Future, Stream};
|
||||||
use http::header::CONTENT_LENGTH;
|
use http::header::{CONTENT_TYPE, CONTENT_LENGTH};
|
||||||
|
|
||||||
use bytes::IntoBuf;
|
use bytes::IntoBuf;
|
||||||
use prost::Message;
|
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 handler::Responder;
|
||||||
use httpmessage::HttpMessage;
|
use httpmessage::HttpMessage;
|
||||||
use httprequest::HttpRequest;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct ProtoBuf<T: Message>(pub T);
|
pub struct ProtoBuf<T: Message>(pub T);
|
||||||
@ -32,9 +76,6 @@ impl<T: Message> Responder for ProtoBuf<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct ProtoBufBody<T, U: Message + Default>{
|
pub struct ProtoBufBody<T, U: Message + Default>{
|
||||||
limit: usize,
|
limit: usize,
|
||||||
ct: &'static str,
|
ct: &'static str,
|
||||||
@ -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()
|
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)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user