mirror of
https://github.com/actix/actix-extras.git
synced 2025-01-22 23:05:56 +01:00
add protobuf extractor
This commit is contained in:
parent
bf240121b9
commit
69c73c52cd
@ -1,5 +1,9 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## 0.2.0 (2018-04-10)
|
||||||
|
|
||||||
|
* Provide protobuf extractor
|
||||||
|
|
||||||
## 0.1.0 (2018-03-21)
|
## 0.1.0 (2018-03-21)
|
||||||
|
|
||||||
* First release
|
* First release
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-protobuf"
|
name = "actix-protobuf"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["kingxsp <jin.hb.zh@outlook.com>"]
|
authors = ["kingxsp <jin.hb.zh@outlook.com>"]
|
||||||
description = "Protobuf support for actix-web framework."
|
description = "Protobuf support for actix-web framework."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -24,7 +24,7 @@ futures = "0.1"
|
|||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
|
|
||||||
actix = "0.5"
|
actix = "0.5"
|
||||||
actix-web = "0.4"
|
actix-web = "0.5"
|
||||||
|
|
||||||
prost = "0.2"
|
prost = "0.2"
|
||||||
|
|
||||||
|
13
README.md
13
README.md
@ -6,8 +6,8 @@ Protobuf support for actix-web framework.
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
use actix_web::*;
|
use actix_web::HttpResponse;
|
||||||
use actix_protobuf::*;
|
use actix_protobuf::ProtoBuf;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Message)]
|
#[derive(Clone, Debug, PartialEq, Message)]
|
||||||
@ -18,14 +18,9 @@ pub struct MyObj {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
fn index(msg: ProtoBuf<MyObj>) -> HttpResponse {
|
||||||
req.protobuf()
|
|
||||||
.from_err() // convert all errors into `Error`
|
|
||||||
.and_then(|val: MyObj| {
|
|
||||||
println!("model: {:?}", val);
|
println!("model: {:?}", val);
|
||||||
Ok(httpcodes::HTTPOk.build().protobuf(val)?) // <- send response
|
HttpResponse::Ok().protobuf(val)?) // <- send response
|
||||||
})
|
|
||||||
.responder()
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
81
src/lib.rs
81
src/lib.rs
@ -12,6 +12,8 @@ extern crate prost;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use] extern crate prost_derive;
|
#[macro_use] extern crate prost_derive;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::{Poll, Future, Stream};
|
use futures::{Poll, Future, Stream};
|
||||||
|
|
||||||
@ -20,11 +22,10 @@ use prost::Message;
|
|||||||
use prost::DecodeError as ProtoBufDecodeError;
|
use prost::DecodeError as ProtoBufDecodeError;
|
||||||
use prost::EncodeError as ProtoBufEncodeError;
|
use prost::EncodeError as ProtoBufEncodeError;
|
||||||
|
|
||||||
use actix_web::header::http::{CONTENT_TYPE, CONTENT_LENGTH};
|
use actix_web::http::header::{CONTENT_TYPE, CONTENT_LENGTH};
|
||||||
use actix_web::{Responder, HttpMessage, HttpRequest, HttpResponse};
|
use actix_web::{Responder, HttpMessage, HttpRequest, HttpResponse, FromRequest};
|
||||||
use actix_web::dev::HttpResponseBuilder;
|
use actix_web::dev::HttpResponseBuilder;
|
||||||
use actix_web::error::{Error, PayloadError, ResponseError};
|
use actix_web::error::{Error, PayloadError, ResponseError};
|
||||||
use actix_web::httpcodes::{HttpBadRequest, HttpPayloadTooLarge};
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Fail, Debug)]
|
||||||
@ -50,8 +51,8 @@ impl ResponseError for ProtoBufPayloadError {
|
|||||||
|
|
||||||
fn error_response(&self) -> HttpResponse {
|
fn error_response(&self) -> HttpResponse {
|
||||||
match *self {
|
match *self {
|
||||||
ProtoBufPayloadError::Overflow => HttpPayloadTooLarge.into(),
|
ProtoBufPayloadError::Overflow => HttpResponse::PayloadTooLarge().into(),
|
||||||
_ => HttpBadRequest.into(),
|
_ => HttpResponse::BadRequest().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,10 +69,70 @@ impl From<ProtoBufDecodeError> for ProtoBufPayloadError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ProtoBuf<T: Message>(pub T);
|
pub struct ProtoBuf<T: Message>(pub T);
|
||||||
|
|
||||||
impl<T: Message> Responder for ProtoBuf<T> {
|
impl<T: Message> Deref for ProtoBuf<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Message> DerefMut for ProtoBuf<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Message> fmt::Debug for ProtoBuf<T> where T: fmt::Debug {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "ProtoBuf: {:?}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Message> fmt::Display for ProtoBuf<T> where T: fmt::Display {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProtoBufConfig {
|
||||||
|
limit: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProtoBufConfig {
|
||||||
|
|
||||||
|
/// Change max size of payload. By default max size is 256Kb
|
||||||
|
pub fn limit(&mut self, limit: usize) -> &mut Self {
|
||||||
|
self.limit = limit;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ProtoBufConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
ProtoBufConfig{limit: 262_144}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, S> FromRequest<S> for ProtoBuf<T>
|
||||||
|
where T: Message + Default + 'static, S: 'static
|
||||||
|
{
|
||||||
|
type Config = ProtoBufConfig;
|
||||||
|
type Result = Box<Future<Item=Self, Error=Error>>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||||
|
Box::new(
|
||||||
|
ProtoBufMessage::new(req.clone())
|
||||||
|
.limit(cfg.limit)
|
||||||
|
.from_err()
|
||||||
|
.map(ProtoBuf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Message + Default> Responder for ProtoBuf<T> {
|
||||||
type Item = HttpResponse;
|
type Item = HttpResponse;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -82,8 +143,7 @@ impl<T: Message> Responder for ProtoBuf<T> {
|
|||||||
.and_then(|()| {
|
.and_then(|()| {
|
||||||
Ok(HttpResponse::Ok()
|
Ok(HttpResponse::Ok()
|
||||||
.content_type("application/protobuf")
|
.content_type("application/protobuf")
|
||||||
.body(buf)
|
.body(buf))
|
||||||
.into())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +238,7 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder {
|
|||||||
|
|
||||||
let mut body = Vec::new();
|
let mut body = Vec::new();
|
||||||
value.encode(&mut body).map_err(ProtoBufPayloadError::Serialize)?;
|
value.encode(&mut body).map_err(ProtoBufPayloadError::Serialize)?;
|
||||||
Ok(self.body(body)?)
|
Ok(self.body(body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +282,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Message)]
|
#[derive(Clone, Debug, PartialEq, Message)]
|
||||||
pub struct MyObject {
|
pub struct MyObject {
|
||||||
#[prost(int32, tag="1")]
|
#[prost(int32, tag="1")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user