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
|
||||
|
||||
## 0.2.0 (2018-04-10)
|
||||
|
||||
* Provide protobuf extractor
|
||||
|
||||
## 0.1.0 (2018-03-21)
|
||||
|
||||
* First release
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-protobuf"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["kingxsp <jin.hb.zh@outlook.com>"]
|
||||
description = "Protobuf support for actix-web framework."
|
||||
readme = "README.md"
|
||||
@ -24,7 +24,7 @@ futures = "0.1"
|
||||
failure = "0.1"
|
||||
|
||||
actix = "0.5"
|
||||
actix-web = "0.4"
|
||||
actix-web = "0.5"
|
||||
|
||||
prost = "0.2"
|
||||
|
||||
|
15
README.md
15
README.md
@ -6,8 +6,8 @@ Protobuf support for actix-web framework.
|
||||
## Example
|
||||
|
||||
```rust,ignore
|
||||
use actix_web::*;
|
||||
use actix_protobuf::*;
|
||||
use actix_web::HttpResponse;
|
||||
use actix_protobuf::ProtoBuf;
|
||||
use futures::Future;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Message)]
|
||||
@ -18,14 +18,9 @@ pub struct MyObj {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
||||
req.protobuf()
|
||||
.from_err() // convert all errors into `Error`
|
||||
.and_then(|val: MyObj| {
|
||||
println!("model: {:?}", val);
|
||||
Ok(httpcodes::HTTPOk.build().protobuf(val)?) // <- send response
|
||||
})
|
||||
.responder()
|
||||
fn index(msg: ProtoBuf<MyObj>) -> HttpResponse {
|
||||
println!("model: {:?}", val);
|
||||
HttpResponse::Ok().protobuf(val)?) // <- send response
|
||||
}
|
||||
```
|
||||
|
||||
|
81
src/lib.rs
81
src/lib.rs
@ -12,6 +12,8 @@ extern crate prost;
|
||||
#[cfg(test)]
|
||||
#[macro_use] extern crate prost_derive;
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::{Poll, Future, Stream};
|
||||
|
||||
@ -20,11 +22,10 @@ use prost::Message;
|
||||
use prost::DecodeError as ProtoBufDecodeError;
|
||||
use prost::EncodeError as ProtoBufEncodeError;
|
||||
|
||||
use actix_web::header::http::{CONTENT_TYPE, CONTENT_LENGTH};
|
||||
use actix_web::{Responder, HttpMessage, HttpRequest, HttpResponse};
|
||||
use actix_web::http::header::{CONTENT_TYPE, CONTENT_LENGTH};
|
||||
use actix_web::{Responder, HttpMessage, HttpRequest, HttpResponse, FromRequest};
|
||||
use actix_web::dev::HttpResponseBuilder;
|
||||
use actix_web::error::{Error, PayloadError, ResponseError};
|
||||
use actix_web::httpcodes::{HttpBadRequest, HttpPayloadTooLarge};
|
||||
|
||||
|
||||
#[derive(Fail, Debug)]
|
||||
@ -50,8 +51,8 @@ impl ResponseError for ProtoBufPayloadError {
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
match *self {
|
||||
ProtoBufPayloadError::Overflow => HttpPayloadTooLarge.into(),
|
||||
_ => HttpBadRequest.into(),
|
||||
ProtoBufPayloadError::Overflow => HttpResponse::PayloadTooLarge().into(),
|
||||
_ => HttpResponse::BadRequest().into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,10 +69,70 @@ impl From<ProtoBufDecodeError> for ProtoBufPayloadError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
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 Error = Error;
|
||||
|
||||
@ -82,8 +143,7 @@ impl<T: Message> Responder for ProtoBuf<T> {
|
||||
.and_then(|()| {
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/protobuf")
|
||||
.body(buf)
|
||||
.into())
|
||||
.body(buf))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -178,7 +238,7 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder {
|
||||
|
||||
let mut body = Vec::new();
|
||||
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)]
|
||||
pub struct MyObject {
|
||||
#[prost(int32, tag="1")]
|
||||
|
Loading…
x
Reference in New Issue
Block a user