From 6861e9f71220ee312764f8fdd2b997fcb77fe75d Mon Sep 17 00:00:00 2001 From: kingxsp Date: Tue, 13 Mar 2018 00:21:49 +0800 Subject: [PATCH 01/35] first commit --- .gitignore | 14 ++++++++++++++ CHANGES.md | 0 README.md | 2 ++ 3 files changed, 16 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGES.md create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..42d0755dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +Cargo.lock +target/ +guide/build/ +/gh-pages + +*.so +*.out +*.pyc +*.pid +*.sock +*~ + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 000000000..e69de29bb diff --git a/README.md b/README.md new file mode 100644 index 000000000..9f1928866 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Actix-web Protobuf +Protobuf support for actix-web framework. \ No newline at end of file From e6bffa2b62d8480a02f92764526592fd5fec5149 Mon Sep 17 00:00:00 2001 From: kingxsp Date: Tue, 13 Mar 2018 22:13:21 +0800 Subject: [PATCH 02/35] First release --- CHANGES.md | 5 + Cargo.toml | 37 +++++ examples/prost-example/Cargo.toml | 16 ++ examples/prost-example/client.py | 68 ++++++++ examples/prost-example/src/main.rs | 50 ++++++ examples/prost-example/test.proto | 6 + examples/prost-example/test_pb2.py | 76 +++++++++ src/lib.rs | 21 +++ src/use_prost.rs | 247 +++++++++++++++++++++++++++++ 9 files changed, 526 insertions(+) create mode 100644 Cargo.toml create mode 100644 examples/prost-example/Cargo.toml create mode 100644 examples/prost-example/client.py create mode 100644 examples/prost-example/src/main.rs create mode 100644 examples/prost-example/test.proto create mode 100644 examples/prost-example/test_pb2.py create mode 100644 src/lib.rs create mode 100644 src/use_prost.rs diff --git a/CHANGES.md b/CHANGES.md index e69de29bb..f34c74de5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -0,0 +1,5 @@ +# Changes + +## 0.1.0 (2017-10-23) + +* First release \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..a574d806e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "actix-protobuf" +version = "0.1.0" +authors = ["kingxsp "] + +[lib] +name = "actix_protobuf" +path = "src/lib.rs" + +[features] +default = ["use_prost"] + +use_prost = ["prost"] + + + +[dependencies] +bytes = "0.4" +futures = "0.1" +failure = "0.1" +env_logger = "*" + +actix = "^0.5" +actix-web = "^0.4" + +prost = { version="^0.2", optional = true } + +[dev-dependencies] +http = "^0.1.5" +prost-derive = "^0.2" + + +[workspace] +members = [ + "./", + "examples/prost-example", +] \ No newline at end of file diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml new file mode 100644 index 000000000..6cd47d969 --- /dev/null +++ b/examples/prost-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "prost-example" +version = "0.1.0" +authors = ["kingxsp "] + +[dependencies] +bytes = "0.4" +futures = "0.1" +env_logger = "*" + +prost = "0.2" +prost-derive = "0.2" + +actix = "0.5" +actix-web = "0.4" +actix-protobuf = { path="../../" } \ No newline at end of file diff --git a/examples/prost-example/client.py b/examples/prost-example/client.py new file mode 100644 index 000000000..c55f78885 --- /dev/null +++ b/examples/prost-example/client.py @@ -0,0 +1,68 @@ +# just start server and run client.py + +# wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-python-3.5.1.zip +# unzip protobuf-python-3.5.1.zip.1 +# cd protobuf-3.5.1/python/ +# python3.6 setup.py install + +# pip3.6 install --upgrade pip +# pip3.6 install aiohttp + +# python3.6 client.py + +#!/usr/bin/env python +import test_pb2 +import traceback +import sys + +import asyncio +import aiohttp + +def op(): + try: + obj = test_pb2.MyObj() + obj.number = 9 + obj.name = 'USB' + + #Serialize + sendDataStr = obj.SerializeToString() + #print serialized string value + print('serialized string:', sendDataStr) + #------------------------# + # message transmission # + #------------------------# + receiveDataStr = sendDataStr + receiveData = test_pb2.MyObj() + + #Deserialize + receiveData.ParseFromString(receiveDataStr) + print('pares serialize string, return: devId = ', receiveData.number, ', name = ', receiveData.name) + except(Exception, e): + print(Exception, ':', e) + print(traceback.print_exc()) + errInfo = sys.exc_info() + print(errInfo[0], ':', errInfo[1]) + + +async def fetch(session): + obj = test_pb2.MyObj() + obj.number = 9 + obj.name = 'USB' + async with session.post('http://localhost:8080/', data=obj.SerializeToString(), + headers={"content-type": "application/protobuf"}) as resp: + print(resp.status) + data = await resp.read() + receiveObj = test_pb2.MyObj() + receiveObj.ParseFromString(data) + print(receiveObj) + +async def go(loop): + obj = test_pb2.MyObj() + obj.number = 9 + obj.name = 'USB' + async with aiohttp.ClientSession(loop=loop) as session: + await fetch(session) + +loop = asyncio.get_event_loop() +loop.run_until_complete(go(loop)) +loop.close() \ No newline at end of file diff --git a/examples/prost-example/src/main.rs b/examples/prost-example/src/main.rs new file mode 100644 index 000000000..0b2309859 --- /dev/null +++ b/examples/prost-example/src/main.rs @@ -0,0 +1,50 @@ +extern crate actix; +extern crate actix_web; +extern crate actix_protobuf; +extern crate bytes; +extern crate futures; +extern crate env_logger; +extern crate prost; +#[macro_use] +extern crate prost_derive; + +use actix_web::*; +use actix_protobuf::*; +use futures::Future; + +#[derive(Clone, Debug, PartialEq, Message)] +pub struct MyObj { + #[prost(int32, tag="1")] + pub number: i32, + #[prost(string, tag="2")] + pub name: String, +} + + +fn index(req: HttpRequest) -> Box> { + 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 main() { + ::std::env::set_var("RUST_LOG", "actix_web=info"); + let _ = env_logger::init(); + let sys = actix::System::new("prost-example"); + + let _addr = HttpServer::new(|| { + Application::new() + .middleware(middleware::Logger::default()) + .resource("/", |r| r.method(Method::POST).f(index))}) + .bind("127.0.0.1:8080").unwrap() + .shutdown_timeout(1) + .start(); + + println!("Started http server: 127.0.0.1:8080"); + let _ = sys.run(); +} diff --git a/examples/prost-example/test.proto b/examples/prost-example/test.proto new file mode 100644 index 000000000..8ec278ca4 --- /dev/null +++ b/examples/prost-example/test.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message MyObj { + int32 number = 1; + string name = 2; +} \ No newline at end of file diff --git a/examples/prost-example/test_pb2.py b/examples/prost-example/test_pb2.py new file mode 100644 index 000000000..05e71f3a6 --- /dev/null +++ b/examples/prost-example/test_pb2.py @@ -0,0 +1,76 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='test.proto', + package='', + syntax='proto3', + serialized_pb=_b('\n\ntest.proto\"%\n\x05MyObj\x12\x0e\n\x06number\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\tb\x06proto3') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + + + + +_MYOBJ = _descriptor.Descriptor( + name='MyObj', + full_name='MyObj', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='number', full_name='MyObj.number', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='name', full_name='MyObj.name', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14, + serialized_end=51, +) + +DESCRIPTOR.message_types_by_name['MyObj'] = _MYOBJ + +MyObj = _reflection.GeneratedProtocolMessageType('MyObj', (_message.Message,), dict( + DESCRIPTOR = _MYOBJ, + __module__ = 'test_pb2' + # @@protoc_insertion_point(class_scope:MyObj) + )) +_sym_db.RegisterMessage(MyObj) + + +# @@protoc_insertion_point(module_scope) diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..31b7493fa --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,21 @@ +extern crate actix; +extern crate actix_web; +extern crate bytes; +extern crate futures; +#[macro_use] +extern crate failure; +extern crate env_logger; + +#[cfg(test)] +extern crate http; + +#[cfg(feature="use_prost")] +extern crate prost; +#[cfg(test)] +#[cfg(feature="use_prost")] +#[macro_use] extern crate prost_derive; + +#[cfg(feature="use_prost")] +mod use_prost; +#[cfg(feature="use_prost")] +pub use use_prost::{ ProtoBuf, ProtoBufResponseBuilder, ProtoBufHttpMessage }; \ No newline at end of file diff --git a/src/use_prost.rs b/src/use_prost.rs new file mode 100644 index 000000000..ba3a26867 --- /dev/null +++ b/src/use_prost.rs @@ -0,0 +1,247 @@ +use bytes::{Bytes, BytesMut}; +use futures::{Poll, Future, Stream}; + +use bytes::IntoBuf; +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::dev::HttpResponseBuilder; +use actix_web::error::{Error, PayloadError, ResponseError}; +use actix_web::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, + /// Serialize error + #[fail(display="ProtoBud serialize error: {}", _0)] + Serialize(#[cause] ProtoBufEncodeError), + /// Deserialize error + #[fail(display="ProtoBud 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) + } +} + +#[derive(Debug)] +pub struct ProtoBuf(pub T); + +impl Responder for ProtoBuf { + type Item = HttpResponse; + type Error = Error; + + fn respond_to(self, _: HttpRequest) -> Result { + let mut buf = Vec::new(); + self.0.encode(&mut buf) + .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) + .and_then(|()| { + Ok(HttpResponse::Ok() + .content_type("application/protobuf") + .body(buf) + .into()) + }) + } +} + +pub struct ProtoBufMessage{ + limit: usize, + ct: &'static str, + req: Option, + fut: Option>>, +} + +impl ProtoBufMessage { + + /// Create `ProtoBufMessage` for request. + pub fn new(req: T) -> Self { + ProtoBufMessage{ + limit: 262_144, + req: Some(req), + fut: None, + ct: "application/protobuf", + } + } + + /// Change max size of payload. By default max size is 256Kb + pub fn limit(mut self, limit: usize) -> Self { + self.limit = limit; + self + } + + /// Set allowed content type. + /// + /// By default *application/protobuf* content type is used. Set content type + /// to empty string if you want to disable content type check. + pub fn content_type(mut self, ct: &'static str) -> Self { + self.ct = ct; + self + } +} + +impl Future for ProtoBufMessage + where T: HttpMessage + Stream + 'static +{ + type Item = U; + type Error = ProtoBufPayloadError; + + fn poll(&mut self) -> Poll { + if let Some(req) = self.req.take() { + if let Some(len) = req.headers().get(CONTENT_LENGTH) { + if let Ok(s) = len.to_str() { + if let Ok(len) = s.parse::() { + if len > self.limit { + return Err(ProtoBufPayloadError::Overflow); + } + } else { + return Err(ProtoBufPayloadError::Overflow); + } + } + } + // check content-type + if !self.ct.is_empty() && req.content_type() != self.ct { + return Err(ProtoBufPayloadError::ContentType) + } + + let limit = self.limit; + let fut = req.from_err() + .fold(BytesMut::new(), move |mut body, chunk| { + if (body.len() + chunk.len()) > limit { + Err(ProtoBufPayloadError::Overflow) + } else { + body.extend_from_slice(&chunk); + Ok(body) + } + }) + .and_then(|body| Ok(::decode(&mut body.into_buf())?)); + self.fut = Some(Box::new(fut)); + } + + self.fut.as_mut().expect("ProtoBufBody could not be used second time").poll() + } +} + + +pub trait ProtoBufResponseBuilder { + + fn protobuf(&mut self, value: T) -> Result; +} + +impl ProtoBufResponseBuilder for HttpResponseBuilder { + + fn protobuf(&mut self, value: T) -> Result { + self.header(CONTENT_TYPE, "application/protobuf"); + + let mut body = Vec::new(); + value.encode(&mut body).map_err(|e| ProtoBufPayloadError::Serialize(e))?; + Ok(self.body(body)?) + } +} + + + +pub trait ProtoBufHttpMessage { + fn protobuf(self) -> ProtoBufMessage + where Self: Stream + Sized; +} + +impl ProtoBufHttpMessage for HttpRequest { + + #[inline] + fn protobuf(self) -> ProtoBufMessage + where Self: Stream + Sized + { + ProtoBufMessage::new(self) + } +} + + + +#[cfg(test)] +mod tests { + use super::*; + use http::header; + + impl PartialEq for ProtoBufPayloadError { + fn eq(&self, other: &ProtoBufPayloadError) -> bool { + match *self { + ProtoBufPayloadError::Overflow => match *other { + ProtoBufPayloadError::Overflow => true, + _ => false, + }, + ProtoBufPayloadError::ContentType => match *other { + ProtoBufPayloadError::ContentType => true, + _ => false, + }, + _ => false, + } + } + } + + + #[derive(Clone, Debug, PartialEq, Message)] + pub struct MyObject { + #[prost(int32, tag="1")] + pub number: i32, + #[prost(string, tag="2")] + pub name: String, + } + + #[test] + fn test_protobuf() { + let protobuf = ProtoBuf(MyObject{number: 9 , name: "test".to_owned()}); + let resp = protobuf.respond_to(HttpRequest::default()).unwrap(); + assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf"); + } + + #[test] + fn test_protobuf_message() { + let req = HttpRequest::default(); + let mut protobuf = req.protobuf::(); + assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); + + let mut req = HttpRequest::default(); + req.headers_mut().insert(header::CONTENT_TYPE, + header::HeaderValue::from_static("application/protobuf")); + let mut protobuf = req.protobuf::().content_type("text/protobuf"); + assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); + + let mut req = HttpRequest::default(); + req.headers_mut().insert(header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json")); + req.headers_mut().insert(header::CONTENT_LENGTH, + header::HeaderValue::from_static("10000")); + let mut protobuf = req.protobuf::().limit(100); + assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::Overflow); + } +} \ No newline at end of file From 79fa52a661e27504eb860f27ae6d796b87384464 Mon Sep 17 00:00:00 2001 From: kingxsp Date: Tue, 13 Mar 2018 22:16:20 +0800 Subject: [PATCH 03/35] change first release date --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index f34c74de5..4158f80ab 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,5 @@ # Changes -## 0.1.0 (2017-10-23) +## 0.1.0 (2018-03-12) * First release \ No newline at end of file From e09ff545672e8067a0e8f156dc6cff626e06624a Mon Sep 17 00:00:00 2001 From: kingxsp Date: Wed, 14 Mar 2018 10:07:33 +0800 Subject: [PATCH 04/35] remove features --- Cargo.toml | 9 +-------- src/lib.rs | 4 ---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a574d806e..e060b7abe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,13 +7,6 @@ authors = ["kingxsp "] name = "actix_protobuf" path = "src/lib.rs" -[features] -default = ["use_prost"] - -use_prost = ["prost"] - - - [dependencies] bytes = "0.4" futures = "0.1" @@ -23,7 +16,7 @@ env_logger = "*" actix = "^0.5" actix-web = "^0.4" -prost = { version="^0.2", optional = true } +prost = "^0.2" [dev-dependencies] http = "^0.1.5" diff --git a/src/lib.rs b/src/lib.rs index 31b7493fa..2548c3ac8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,13 +9,9 @@ extern crate env_logger; #[cfg(test)] extern crate http; -#[cfg(feature="use_prost")] extern crate prost; #[cfg(test)] -#[cfg(feature="use_prost")] #[macro_use] extern crate prost_derive; -#[cfg(feature="use_prost")] mod use_prost; -#[cfg(feature="use_prost")] pub use use_prost::{ ProtoBuf, ProtoBufResponseBuilder, ProtoBufHttpMessage }; \ No newline at end of file From da0114a10e8afe9943ef84babe1d38cb98ccf831 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 21 Mar 2018 15:43:32 -0700 Subject: [PATCH 05/35] refacrtor layout --- .travis.yml | 54 ++++++++++ Cargo.toml | 3 +- src/lib.rs | 249 ++++++++++++++++++++++++++++++++++++++++++++++- src/use_prost.rs | 247 ---------------------------------------------- 4 files changed, 302 insertions(+), 251 deletions(-) create mode 100644 .travis.yml delete mode 100644 src/use_prost.rs diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..32fe873ae --- /dev/null +++ b/.travis.yml @@ -0,0 +1,54 @@ +language: rust +rust: + - 1.21.0 + - stable + - beta + - nightly + +sudo: required +dist: trusty + +env: + global: + - RUSTFLAGS="-C link-dead-code" + +addons: + apt: + packages: + - libcurl4-openssl-dev + - libelf-dev + - libdw-dev + - cmake + - gcc + - binutils-dev + - libiberty-dev + +# Add clippy +before_script: + - | + if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then + ( ( cargo install clippy && export CLIPPY=true ) || export CLIPPY=false ); + fi + - export PATH=$PATH:~/.cargo/bin + +script: + - | + if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then + USE_SKEPTIC=1 cargo test + else + cargo test + fi + - | + if [[ "$TRAVIS_RUST_VERSION" == "nightly" && $CLIPPY ]]; then + cargo clippy + fi + +# Upload docs +after_success: + - | + if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "nightly" ]]; then + bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh) + USE_SKEPTIC=1 cargo tarpaulin --out Xml + bash <(curl -s https://codecov.io/bash) + echo "Uploaded code coverage" + fi diff --git a/Cargo.toml b/Cargo.toml index e060b7abe..6a45a2405 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,8 @@ prost = "^0.2" http = "^0.1.5" prost-derive = "^0.2" - [workspace] members = [ "./", "examples/prost-example", -] \ No newline at end of file +] diff --git a/src/lib.rs b/src/lib.rs index 2548c3ac8..5cb2f849d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,5 +13,250 @@ extern crate prost; #[cfg(test)] #[macro_use] extern crate prost_derive; -mod use_prost; -pub use use_prost::{ ProtoBuf, ProtoBufResponseBuilder, ProtoBufHttpMessage }; \ No newline at end of file +use bytes::{Bytes, BytesMut}; +use futures::{Poll, Future, Stream}; + +use bytes::IntoBuf; +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::dev::HttpResponseBuilder; +use actix_web::error::{Error, PayloadError, ResponseError}; +use actix_web::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, + /// Serialize error + #[fail(display="ProtoBud serialize error: {}", _0)] + Serialize(#[cause] ProtoBufEncodeError), + /// Deserialize error + #[fail(display="ProtoBud 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) + } +} + +#[derive(Debug)] +pub struct ProtoBuf(pub T); + +impl Responder for ProtoBuf { + type Item = HttpResponse; + type Error = Error; + + fn respond_to(self, _: HttpRequest) -> Result { + let mut buf = Vec::new(); + self.0.encode(&mut buf) + .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) + .and_then(|()| { + Ok(HttpResponse::Ok() + .content_type("application/protobuf") + .body(buf) + .into()) + }) + } +} + +pub struct ProtoBufMessage{ + limit: usize, + ct: &'static str, + req: Option, + fut: Option>>, +} + +impl ProtoBufMessage { + + /// Create `ProtoBufMessage` for request. + pub fn new(req: T) -> Self { + ProtoBufMessage{ + limit: 262_144, + req: Some(req), + fut: None, + ct: "application/protobuf", + } + } + + /// Change max size of payload. By default max size is 256Kb + pub fn limit(mut self, limit: usize) -> Self { + self.limit = limit; + self + } + + /// Set allowed content type. + /// + /// By default *application/protobuf* content type is used. Set content type + /// to empty string if you want to disable content type check. + pub fn content_type(mut self, ct: &'static str) -> Self { + self.ct = ct; + self + } +} + +impl Future for ProtoBufMessage + where T: HttpMessage + Stream + 'static +{ + type Item = U; + type Error = ProtoBufPayloadError; + + fn poll(&mut self) -> Poll { + if let Some(req) = self.req.take() { + if let Some(len) = req.headers().get(CONTENT_LENGTH) { + if let Ok(s) = len.to_str() { + if let Ok(len) = s.parse::() { + if len > self.limit { + return Err(ProtoBufPayloadError::Overflow); + } + } else { + return Err(ProtoBufPayloadError::Overflow); + } + } + } + // check content-type + if !self.ct.is_empty() && req.content_type() != self.ct { + return Err(ProtoBufPayloadError::ContentType) + } + + let limit = self.limit; + let fut = req.from_err() + .fold(BytesMut::new(), move |mut body, chunk| { + if (body.len() + chunk.len()) > limit { + Err(ProtoBufPayloadError::Overflow) + } else { + body.extend_from_slice(&chunk); + Ok(body) + } + }) + .and_then(|body| Ok(::decode(&mut body.into_buf())?)); + self.fut = Some(Box::new(fut)); + } + + self.fut.as_mut().expect("ProtoBufBody could not be used second time").poll() + } +} + + +pub trait ProtoBufResponseBuilder { + + fn protobuf(&mut self, value: T) -> Result; +} + +impl ProtoBufResponseBuilder for HttpResponseBuilder { + + fn protobuf(&mut self, value: T) -> Result { + self.header(CONTENT_TYPE, "application/protobuf"); + + let mut body = Vec::new(); + value.encode(&mut body).map_err(ProtoBufPayloadError::Serialize)?; + Ok(self.body(body)?) + } +} + + + +pub trait ProtoBufHttpMessage { + fn protobuf(self) -> ProtoBufMessage + where Self: Stream + Sized; +} + +impl ProtoBufHttpMessage for HttpRequest { + + #[inline] + fn protobuf(self) -> ProtoBufMessage + where Self: Stream + Sized + { + ProtoBufMessage::new(self) + } +} + + + +#[cfg(test)] +mod tests { + use super::*; + use http::header; + + impl PartialEq for ProtoBufPayloadError { + fn eq(&self, other: &ProtoBufPayloadError) -> bool { + match *self { + ProtoBufPayloadError::Overflow => match *other { + ProtoBufPayloadError::Overflow => true, + _ => false, + }, + ProtoBufPayloadError::ContentType => match *other { + ProtoBufPayloadError::ContentType => true, + _ => false, + }, + _ => false, + } + } + } + + + #[derive(Clone, Debug, PartialEq, Message)] + pub struct MyObject { + #[prost(int32, tag="1")] + pub number: i32, + #[prost(string, tag="2")] + pub name: String, + } + + #[test] + fn test_protobuf() { + let protobuf = ProtoBuf(MyObject{number: 9 , name: "test".to_owned()}); + let resp = protobuf.respond_to(HttpRequest::default()).unwrap(); + assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf"); + } + + #[test] + fn test_protobuf_message() { + let req = HttpRequest::default(); + let mut protobuf = req.protobuf::(); + assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); + + let mut req = HttpRequest::default(); + req.headers_mut().insert(header::CONTENT_TYPE, + header::HeaderValue::from_static("application/protobuf")); + let mut protobuf = req.protobuf::().content_type("text/protobuf"); + assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); + + let mut req = HttpRequest::default(); + req.headers_mut().insert(header::CONTENT_TYPE, + header::HeaderValue::from_static("application/json")); + req.headers_mut().insert(header::CONTENT_LENGTH, + header::HeaderValue::from_static("10000")); + let mut protobuf = req.protobuf::().limit(100); + assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::Overflow); + } +} diff --git a/src/use_prost.rs b/src/use_prost.rs deleted file mode 100644 index ba3a26867..000000000 --- a/src/use_prost.rs +++ /dev/null @@ -1,247 +0,0 @@ -use bytes::{Bytes, BytesMut}; -use futures::{Poll, Future, Stream}; - -use bytes::IntoBuf; -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::dev::HttpResponseBuilder; -use actix_web::error::{Error, PayloadError, ResponseError}; -use actix_web::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, - /// Serialize error - #[fail(display="ProtoBud serialize error: {}", _0)] - Serialize(#[cause] ProtoBufEncodeError), - /// Deserialize error - #[fail(display="ProtoBud 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) - } -} - -#[derive(Debug)] -pub struct ProtoBuf(pub T); - -impl Responder for ProtoBuf { - type Item = HttpResponse; - type Error = Error; - - fn respond_to(self, _: HttpRequest) -> Result { - let mut buf = Vec::new(); - self.0.encode(&mut buf) - .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) - .and_then(|()| { - Ok(HttpResponse::Ok() - .content_type("application/protobuf") - .body(buf) - .into()) - }) - } -} - -pub struct ProtoBufMessage{ - limit: usize, - ct: &'static str, - req: Option, - fut: Option>>, -} - -impl ProtoBufMessage { - - /// Create `ProtoBufMessage` for request. - pub fn new(req: T) -> Self { - ProtoBufMessage{ - limit: 262_144, - req: Some(req), - fut: None, - ct: "application/protobuf", - } - } - - /// Change max size of payload. By default max size is 256Kb - pub fn limit(mut self, limit: usize) -> Self { - self.limit = limit; - self - } - - /// Set allowed content type. - /// - /// By default *application/protobuf* content type is used. Set content type - /// to empty string if you want to disable content type check. - pub fn content_type(mut self, ct: &'static str) -> Self { - self.ct = ct; - self - } -} - -impl Future for ProtoBufMessage - where T: HttpMessage + Stream + 'static -{ - type Item = U; - type Error = ProtoBufPayloadError; - - fn poll(&mut self) -> Poll { - if let Some(req) = self.req.take() { - if let Some(len) = req.headers().get(CONTENT_LENGTH) { - if let Ok(s) = len.to_str() { - if let Ok(len) = s.parse::() { - if len > self.limit { - return Err(ProtoBufPayloadError::Overflow); - } - } else { - return Err(ProtoBufPayloadError::Overflow); - } - } - } - // check content-type - if !self.ct.is_empty() && req.content_type() != self.ct { - return Err(ProtoBufPayloadError::ContentType) - } - - let limit = self.limit; - let fut = req.from_err() - .fold(BytesMut::new(), move |mut body, chunk| { - if (body.len() + chunk.len()) > limit { - Err(ProtoBufPayloadError::Overflow) - } else { - body.extend_from_slice(&chunk); - Ok(body) - } - }) - .and_then(|body| Ok(::decode(&mut body.into_buf())?)); - self.fut = Some(Box::new(fut)); - } - - self.fut.as_mut().expect("ProtoBufBody could not be used second time").poll() - } -} - - -pub trait ProtoBufResponseBuilder { - - fn protobuf(&mut self, value: T) -> Result; -} - -impl ProtoBufResponseBuilder for HttpResponseBuilder { - - fn protobuf(&mut self, value: T) -> Result { - self.header(CONTENT_TYPE, "application/protobuf"); - - let mut body = Vec::new(); - value.encode(&mut body).map_err(|e| ProtoBufPayloadError::Serialize(e))?; - Ok(self.body(body)?) - } -} - - - -pub trait ProtoBufHttpMessage { - fn protobuf(self) -> ProtoBufMessage - where Self: Stream + Sized; -} - -impl ProtoBufHttpMessage for HttpRequest { - - #[inline] - fn protobuf(self) -> ProtoBufMessage - where Self: Stream + Sized - { - ProtoBufMessage::new(self) - } -} - - - -#[cfg(test)] -mod tests { - use super::*; - use http::header; - - impl PartialEq for ProtoBufPayloadError { - fn eq(&self, other: &ProtoBufPayloadError) -> bool { - match *self { - ProtoBufPayloadError::Overflow => match *other { - ProtoBufPayloadError::Overflow => true, - _ => false, - }, - ProtoBufPayloadError::ContentType => match *other { - ProtoBufPayloadError::ContentType => true, - _ => false, - }, - _ => false, - } - } - } - - - #[derive(Clone, Debug, PartialEq, Message)] - pub struct MyObject { - #[prost(int32, tag="1")] - pub number: i32, - #[prost(string, tag="2")] - pub name: String, - } - - #[test] - fn test_protobuf() { - let protobuf = ProtoBuf(MyObject{number: 9 , name: "test".to_owned()}); - let resp = protobuf.respond_to(HttpRequest::default()).unwrap(); - assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf"); - } - - #[test] - fn test_protobuf_message() { - let req = HttpRequest::default(); - let mut protobuf = req.protobuf::(); - assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); - - let mut req = HttpRequest::default(); - req.headers_mut().insert(header::CONTENT_TYPE, - header::HeaderValue::from_static("application/protobuf")); - let mut protobuf = req.protobuf::().content_type("text/protobuf"); - assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); - - let mut req = HttpRequest::default(); - req.headers_mut().insert(header::CONTENT_TYPE, - header::HeaderValue::from_static("application/json")); - req.headers_mut().insert(header::CONTENT_LENGTH, - header::HeaderValue::from_static("10000")); - let mut protobuf = req.protobuf::().limit(100); - assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::Overflow); - } -} \ No newline at end of file From c4ce45b092b44a42a7efb3fa7f49c63c4662d35a Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 21 Mar 2018 15:46:27 -0700 Subject: [PATCH 06/35] update readme --- README.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f1928866..9343f1ddb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,30 @@ -# Actix-web Protobuf -Protobuf support for actix-web framework. \ No newline at end of file +# Actix-web ProtoBuf [![Build Status](https://travis-ci.org/actix/actix-protobuf.svg?branch=master)](https://travis-ci.org/actix/actix-protobuf) [![codecov](https://codecov.io/gh/actix/actix-protobuf/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-protobuf) [![crates.io](http://meritbadge.herokuapp.com/actix-web)](https://crates.io/crates/actix-protobuf) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Protobuf support for actix-web framework. + + +## Example + +```rust,ignore +use actix_web::*; +use actix_protobuf::*; +use futures::Future; + +#[derive(Clone, Debug, PartialEq, Message)] +pub struct MyObj { + #[prost(int32, tag="1")] + pub number: i32, + #[prost(string, tag="2")] + pub name: String, +} + +fn index(req: HttpRequest) -> Box> { + 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() +} +``` From fd54419abde819ef1a189b07d41af8bf4b410f62 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 21 Mar 2018 15:49:58 -0700 Subject: [PATCH 07/35] update cargo metadata --- CHANGES.md | 4 ++-- Cargo.toml | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4158f80ab..bde9f2c62 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,5 @@ # Changes -## 0.1.0 (2018-03-12) +## 0.1.0 (2018-03-21) -* First release \ No newline at end of file +* First release diff --git a/Cargo.toml b/Cargo.toml index 6a45a2405..d4354d266 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,17 @@ name = "actix-protobuf" version = "0.1.0" authors = ["kingxsp "] +description = "Protobuf support for actix-web framework." +readme = "README.md" +keywords = ["actix"] +homepage = "https://github.com/actix/actix-protobuf" +license = "MIT/Apache-2.0" +exclude = [".gitignore", ".travis.yml", ".cargo/config", + "appveyor.yml", "/examples/**"] + +[badges] +travis-ci = { repository = "actix/actix-protobuf", branch = "master" } +codecov = { repository = "actix/actix-protobuf", branch = "master", service = "github" } [lib] name = "actix_protobuf" From b56b25653a623a9e431aa30e240996170a48e5e0 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 21 Mar 2018 15:50:38 -0700 Subject: [PATCH 08/35] license --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 9343f1ddb..812e472dd 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,12 @@ fn index(req: HttpRequest) -> Box> { .responder() } ``` + +## License + +This project is licensed under either of + +* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) +* MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) + +at your option. From 7eba795f7af16b4669af11f5c4abe25776c9c2d6 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 21 Mar 2018 15:52:51 -0700 Subject: [PATCH 09/35] fix crates link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 812e472dd..da34f24b9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Actix-web ProtoBuf [![Build Status](https://travis-ci.org/actix/actix-protobuf.svg?branch=master)](https://travis-ci.org/actix/actix-protobuf) [![codecov](https://codecov.io/gh/actix/actix-protobuf/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-protobuf) [![crates.io](http://meritbadge.herokuapp.com/actix-web)](https://crates.io/crates/actix-protobuf) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# Actix-web ProtoBuf [![Build Status](https://travis-ci.org/actix/actix-protobuf.svg?branch=master)](https://travis-ci.org/actix/actix-protobuf) [![codecov](https://codecov.io/gh/actix/actix-protobuf/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-protobuf) [![crates.io](http://meritbadge.herokuapp.com/actix-protobuf)](https://crates.io/crates/actix-protobuf) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Protobuf support for actix-web framework. From bf240121b9fa236ba10b3d4d2f0b4f9ff594dc16 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 21 Mar 2018 15:58:37 -0700 Subject: [PATCH 10/35] remove unused dependency --- Cargo.toml | 7 +++---- src/lib.rs | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d4354d266..55155801d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,12 +22,11 @@ path = "src/lib.rs" bytes = "0.4" futures = "0.1" failure = "0.1" -env_logger = "*" -actix = "^0.5" -actix-web = "^0.4" +actix = "0.5" +actix-web = "0.4" -prost = "^0.2" +prost = "0.2" [dev-dependencies] http = "^0.1.5" diff --git a/src/lib.rs b/src/lib.rs index 5cb2f849d..0f3b71e00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,6 @@ extern crate bytes; extern crate futures; #[macro_use] extern crate failure; -extern crate env_logger; #[cfg(test)] extern crate http; From 69c73c52cda487c7c40e964c05e088ab89cc2ed5 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 10 Apr 2018 12:40:11 -0700 Subject: [PATCH 11/35] add protobuf extractor --- CHANGES.md | 4 +++ Cargo.toml | 4 +-- README.md | 15 ++++------ src/lib.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bde9f2c62..5da5a01f1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## 0.2.0 (2018-04-10) + +* Provide protobuf extractor + ## 0.1.0 (2018-03-21) * First release diff --git a/Cargo.toml b/Cargo.toml index 55155801d..ed3cd7099 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-protobuf" -version = "0.1.0" +version = "0.2.0" authors = ["kingxsp "] 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" diff --git a/README.md b/README.md index da34f24b9..00c0d5627 100644 --- a/README.md +++ b/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> { - 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) -> HttpResponse { + println!("model: {:?}", val); + HttpResponse::Ok().protobuf(val)?) // <- send response } ``` diff --git a/src/lib.rs b/src/lib.rs index 0f3b71e00..0981145e7 100644 --- a/src/lib.rs +++ b/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 for ProtoBufPayloadError { } } -#[derive(Debug)] pub struct ProtoBuf(pub T); -impl Responder for ProtoBuf { +impl Deref for ProtoBuf { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl DerefMut for ProtoBuf { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl fmt::Debug for ProtoBuf where T: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ProtoBuf: {:?}", self.0) + } +} + +impl fmt::Display for ProtoBuf 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 FromRequest for ProtoBuf + where T: Message + Default + 'static, S: 'static +{ + type Config = ProtoBufConfig; + type Result = Box>; + + #[inline] + fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { + Box::new( + ProtoBufMessage::new(req.clone()) + .limit(cfg.limit) + .from_err() + .map(ProtoBuf)) + } +} + +impl Responder for ProtoBuf { type Item = HttpResponse; type Error = Error; @@ -82,8 +143,7 @@ impl Responder for ProtoBuf { .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")] From d9ba78526e36cb7276249a8a0d95b2099e9f9272 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 10 Apr 2018 12:41:26 -0700 Subject: [PATCH 12/35] update readme example --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 00c0d5627..e881d063d 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@ Protobuf support for actix-web framework. ## Example ```rust,ignore -use actix_web::HttpResponse; +use actix_web::{HttpResponse, Result}; use actix_protobuf::ProtoBuf; -use futures::Future; #[derive(Clone, Debug, PartialEq, Message)] pub struct MyObj { @@ -18,9 +17,9 @@ pub struct MyObj { pub name: String, } -fn index(msg: ProtoBuf) -> HttpResponse { +fn index(msg: ProtoBuf) -> Result { println!("model: {:?}", val); - HttpResponse::Ok().protobuf(val)?) // <- send response + HttpResponse::Ok().protobuf(val) // <- send response } ``` From 4273b9506614c944a8eeac199036f20215ec56d6 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 10 Apr 2018 12:42:41 -0700 Subject: [PATCH 13/35] fix readme example --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e881d063d..48b8afdae 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ pub struct MyObj { } fn index(msg: ProtoBuf) -> Result { - println!("model: {:?}", val); - HttpResponse::Ok().protobuf(val) // <- send response + println!("model: {:?}", msg); + HttpResponse::Ok().protobuf(msg) // <- send response } ``` From 9ac0edbac6d6272d4edd7421f96be905d7d701c3 Mon Sep 17 00:00:00 2001 From: kingxsp Date: Wed, 11 Apr 2018 14:39:19 +0800 Subject: [PATCH 14/35] update example --- README.md | 2 +- examples/prost-example/Cargo.toml | 5 ++--- examples/prost-example/src/main.rs | 23 ++++++++--------------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 48b8afdae..e5d824d70 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ pub struct MyObj { fn index(msg: ProtoBuf) -> Result { println!("model: {:?}", msg); - HttpResponse::Ok().protobuf(msg) // <- send response + HttpResponse::Ok().protobuf(msg.0) // <- send response } ``` diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index 6cd47d969..3f414ea01 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -1,16 +1,15 @@ [package] name = "prost-example" -version = "0.1.0" +version = "0.2.0" authors = ["kingxsp "] [dependencies] bytes = "0.4" -futures = "0.1" env_logger = "*" prost = "0.2" prost-derive = "0.2" actix = "0.5" -actix-web = "0.4" +actix-web = "0.5" actix-protobuf = { path="../../" } \ No newline at end of file diff --git a/examples/prost-example/src/main.rs b/examples/prost-example/src/main.rs index 0b2309859..c384094a1 100644 --- a/examples/prost-example/src/main.rs +++ b/examples/prost-example/src/main.rs @@ -1,8 +1,7 @@ +extern crate bytes; extern crate actix; extern crate actix_web; extern crate actix_protobuf; -extern crate bytes; -extern crate futures; extern crate env_logger; extern crate prost; #[macro_use] @@ -10,7 +9,6 @@ extern crate prost_derive; use actix_web::*; use actix_protobuf::*; -use futures::Future; #[derive(Clone, Debug, PartialEq, Message)] pub struct MyObj { @@ -21,26 +19,21 @@ pub struct MyObj { } -fn index(req: HttpRequest) -> Box> { - 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) -> Result { + println!("model: {:?}", msg); + HttpResponse::Ok().protobuf(msg.0) // <- send response } fn main() { ::std::env::set_var("RUST_LOG", "actix_web=info"); - let _ = env_logger::init(); + env_logger::init(); let sys = actix::System::new("prost-example"); - let _addr = HttpServer::new(|| { - Application::new() + server::new(|| { + App::new() .middleware(middleware::Logger::default()) - .resource("/", |r| r.method(Method::POST).f(index))}) + .resource("/", |r| r.method(http::Method::POST).with(index))}) .bind("127.0.0.1:8080").unwrap() .shutdown_timeout(1) .start(); From ca37d058470ef8d669d70cb510206a85438b0be9 Mon Sep 17 00:00:00 2001 From: Chris Dituri Date: Wed, 11 Jul 2018 11:18:22 -0500 Subject: [PATCH 15/35] fix typo in Fail display of ProtoBufEncodeError and ProtoBufDecodeError Signed-off-by: Chris Dituri --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0981145e7..631a7da1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,10 +37,10 @@ pub enum ProtoBufPayloadError { #[fail(display="Content type error")] ContentType, /// Serialize error - #[fail(display="ProtoBud serialize error: {}", _0)] + #[fail(display="ProtoBuf serialize error: {}", _0)] Serialize(#[cause] ProtoBufEncodeError), /// Deserialize error - #[fail(display="ProtoBud deserialize error: {}", _0)] + #[fail(display="ProtoBuf deserialize error: {}", _0)] Deserialize(#[cause] ProtoBufDecodeError), /// Payload error #[fail(display="Error that occur during reading payload: {}", _0)] From def07f58c8645bf4614585f622bdb9e274e15bfa Mon Sep 17 00:00:00 2001 From: kingxsp Date: Thu, 7 Mar 2019 14:19:57 +0800 Subject: [PATCH 16/35] Upgrade to actix-web 0.7.18 --- CHANGES.md | 4 + Cargo.toml | 12 +-- examples/prost-example/Cargo.toml | 10 +- examples/prost-example/src/main.rs | 2 +- src/lib.rs | 153 ++++++++++++++++------------- 5 files changed, 100 insertions(+), 81 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5da5a01f1..e631f811d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## 0.3.0 (2019-03-07) + +* Upgrade to actix-web 0.7.18 + ## 0.2.0 (2018-04-10) * Provide protobuf extractor diff --git a/Cargo.toml b/Cargo.toml index ed3cd7099..2c07a39df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-protobuf" -version = "0.2.0" +version = "0.3.0" authors = ["kingxsp "] description = "Protobuf support for actix-web framework." readme = "README.md" @@ -23,14 +23,14 @@ bytes = "0.4" futures = "0.1" failure = "0.1" -actix = "0.5" -actix-web = "0.5" +actix = "0.7" +actix-web = "0.7" -prost = "0.2" +prost = "0.4" [dev-dependencies] -http = "^0.1.5" -prost-derive = "^0.2" +http = "^0.1" +prost-derive = "^0.4" [workspace] members = [ diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index 3f414ea01..e797e7833 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "prost-example" -version = "0.2.0" +version = "0.3.0" authors = ["kingxsp "] [dependencies] bytes = "0.4" env_logger = "*" -prost = "0.2" -prost-derive = "0.2" +prost = "0.4" +prost-derive = "0.4" -actix = "0.5" -actix-web = "0.5" +actix = "0.7" +actix-web = "0.7" actix-protobuf = { path="../../" } \ No newline at end of file diff --git a/examples/prost-example/src/main.rs b/examples/prost-example/src/main.rs index c384094a1..d61ea1402 100644 --- a/examples/prost-example/src/main.rs +++ b/examples/prost-example/src/main.rs @@ -10,7 +10,7 @@ extern crate prost_derive; use actix_web::*; use actix_protobuf::*; -#[derive(Clone, Debug, PartialEq, Message)] +#[derive(Clone, PartialEq, Message)] pub struct MyObj { #[prost(int32, tag="1")] pub number: i32, diff --git a/src/lib.rs b/src/lib.rs index 631a7da1a..a461763eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,14 +14,13 @@ extern crate prost; use std::fmt; use std::ops::{Deref, DerefMut}; -use bytes::{Bytes, BytesMut}; -use futures::{Poll, Future, Stream}; -use bytes::IntoBuf; +use bytes::{BytesMut, IntoBuf}; use prost::Message; use prost::DecodeError as ProtoBufDecodeError; use prost::EncodeError as ProtoBufEncodeError; +use futures::{Poll, Future, Stream}; use actix_web::http::header::{CONTENT_TYPE, CONTENT_LENGTH}; use actix_web::{Responder, HttpMessage, HttpRequest, HttpResponse, FromRequest}; use actix_web::dev::HttpResponseBuilder; @@ -125,7 +124,7 @@ impl FromRequest for ProtoBuf #[inline] fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { Box::new( - ProtoBufMessage::new(req.clone()) + ProtoBufMessage::new(req) .limit(cfg.limit) .from_err() .map(ProtoBuf)) @@ -136,7 +135,7 @@ impl Responder for ProtoBuf { type Item = HttpResponse; type Error = Error; - fn respond_to(self, _: HttpRequest) -> Result { + fn respond_to(self, _: &HttpRequest) -> Result { let mut buf = Vec::new(); self.0.encode(&mut buf) .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) @@ -148,22 +147,43 @@ impl Responder for ProtoBuf { } } -pub struct ProtoBufMessage{ +pub struct ProtoBufMessage{ limit: usize, - ct: &'static str, - req: Option, + length: Option, + stream: Option, + err: Option, fut: Option>>, } -impl ProtoBufMessage { +impl ProtoBufMessage { /// Create `ProtoBufMessage` for request. - pub fn new(req: T) -> Self { - ProtoBufMessage{ + pub fn new(req: &T) -> Self { + if req.content_type() != "application/protobuf" { + return ProtoBufMessage { + limit: 262_144, + length: None, + stream: None, + fut: None, + err: Some(ProtoBufPayloadError::ContentType), + }; + } + + let mut len = None; + if let Some(l) = req.headers().get(CONTENT_LENGTH) { + if let Ok(s) = l.to_str() { + if let Ok(l) = s.parse::() { + len = Some(l) + } + } + } + + ProtoBufMessage { limit: 262_144, - req: Some(req), + length: len, + stream: Some(req.payload()), fut: None, - ct: "application/protobuf", + err: None, } } @@ -172,56 +192,45 @@ impl ProtoBufMessage { self.limit = limit; self } - - /// Set allowed content type. - /// - /// By default *application/protobuf* content type is used. Set content type - /// to empty string if you want to disable content type check. - pub fn content_type(mut self, ct: &'static str) -> Self { - self.ct = ct; - self - } } impl Future for ProtoBufMessage - where T: HttpMessage + Stream + 'static +where T: HttpMessage + 'static { type Item = U; type Error = ProtoBufPayloadError; fn poll(&mut self) -> Poll { - if let Some(req) = self.req.take() { - if let Some(len) = req.headers().get(CONTENT_LENGTH) { - if let Ok(s) = len.to_str() { - if let Ok(len) = s.parse::() { - if len > self.limit { - return Err(ProtoBufPayloadError::Overflow); - } - } else { - return Err(ProtoBufPayloadError::Overflow); - } - } - } - // check content-type - if !self.ct.is_empty() && req.content_type() != self.ct { - return Err(ProtoBufPayloadError::ContentType) - } - - let limit = self.limit; - let fut = req.from_err() - .fold(BytesMut::new(), move |mut body, chunk| { - if (body.len() + chunk.len()) > limit { - Err(ProtoBufPayloadError::Overflow) - } else { - body.extend_from_slice(&chunk); - Ok(body) - } - }) - .and_then(|body| Ok(::decode(&mut body.into_buf())?)); - self.fut = Some(Box::new(fut)); + if let Some(ref mut fut) = self.fut { + return fut.poll(); } - self.fut.as_mut().expect("ProtoBufBody could not be used second time").poll() + if let Some(err) = self.err.take() { + return Err(err); + } + + let limit = self.limit; + if let Some(len) = self.length.take() { + if len > limit { + return Err(ProtoBufPayloadError::Overflow); + } + } + + let fut = self + .stream + .take() + .expect("ProtoBufMessage could not be used second time") + .from_err() + .fold(BytesMut::with_capacity(8192), move |mut body, chunk| { + if (body.len() + chunk.len()) > limit { + Err(ProtoBufPayloadError::Overflow) + } else { + body.extend_from_slice(&chunk); + Ok(body) + } + }).and_then(|body| Ok(::decode(&mut body.into_buf())?)); + self.fut = Some(Box::new(fut)); + self.poll() } } @@ -245,15 +254,15 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder { pub trait ProtoBufHttpMessage { - fn protobuf(self) -> ProtoBufMessage - where Self: Stream + Sized; + fn protobuf(&self) -> ProtoBufMessage + where Self: HttpMessage + 'static; } impl ProtoBufHttpMessage for HttpRequest { #[inline] - fn protobuf(self) -> ProtoBufMessage - where Self: Stream + Sized + fn protobuf(&self) -> ProtoBufMessage + where Self: HttpMessage + 'static { ProtoBufMessage::new(self) } @@ -265,6 +274,7 @@ impl ProtoBufHttpMessage for HttpRequest { mod tests { use super::*; use http::header; + use actix_web::test::TestRequest; impl PartialEq for ProtoBufPayloadError { fn eq(&self, other: &ProtoBufPayloadError) -> bool { @@ -282,7 +292,7 @@ mod tests { } } - #[derive(Clone, Debug, PartialEq, Message)] + #[derive(Clone, PartialEq, Message)] pub struct MyObject { #[prost(int32, tag="1")] pub number: i32, @@ -293,27 +303,32 @@ mod tests { #[test] fn test_protobuf() { let protobuf = ProtoBuf(MyObject{number: 9 , name: "test".to_owned()}); - let resp = protobuf.respond_to(HttpRequest::default()).unwrap(); + let resp = protobuf.respond_to(&TestRequest::default().finish()).unwrap(); assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf"); } #[test] fn test_protobuf_message() { - let req = HttpRequest::default(); + let req = TestRequest::default().finish(); let mut protobuf = req.protobuf::(); assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); - let mut req = HttpRequest::default(); - req.headers_mut().insert(header::CONTENT_TYPE, - header::HeaderValue::from_static("application/protobuf")); - let mut protobuf = req.protobuf::().content_type("text/protobuf"); + let req = TestRequest::default() + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/text"), + ).finish(); + let mut protobuf = req.protobuf::(); assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); - let mut req = HttpRequest::default(); - req.headers_mut().insert(header::CONTENT_TYPE, - header::HeaderValue::from_static("application/json")); - req.headers_mut().insert(header::CONTENT_LENGTH, - header::HeaderValue::from_static("10000")); + let req = TestRequest::default() + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/protobuf"), + ).header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("10000"), + ).finish(); let mut protobuf = req.protobuf::().limit(100); assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::Overflow); } From 5ab0474781dc1b02eee10971f44f300a6d6144a6 Mon Sep 17 00:00:00 2001 From: Stefan Puhlmann Date: Sun, 12 May 2019 15:49:47 +0200 Subject: [PATCH 17/35] Making library compatible with actix-web 1.0 --- Cargo.toml | 6 +- examples/prost-example/Cargo.toml | 4 +- src/lib.rs | 114 +++++++++++++----------------- 3 files changed, 54 insertions(+), 70 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c07a39df..f0770489c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,10 +21,10 @@ path = "src/lib.rs" [dependencies] bytes = "0.4" futures = "0.1" -failure = "0.1" +derive_more = "0.14" -actix = "0.7" -actix-web = "0.7" +actix = "0.8.1" +actix-web = "1.0.0-b3" prost = "0.4" diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index e797e7833..18a6ffc8f 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -10,6 +10,6 @@ env_logger = "*" prost = "0.4" prost-derive = "0.4" -actix = "0.7" -actix-web = "0.7" +actix = "0.8.1" +actix-web = "1.0.0-b3" actix-protobuf = { path="../../" } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a461763eb..7c0811879 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,7 @@ extern crate actix; extern crate actix_web; extern crate bytes; extern crate futures; -#[macro_use] -extern crate failure; +extern crate derive_more; #[cfg(test)] extern crate http; @@ -13,6 +12,7 @@ extern crate prost; #[macro_use] extern crate prost_derive; use std::fmt; +use derive_more::Display; use std::ops::{Deref, DerefMut}; use bytes::{BytesMut, IntoBuf}; @@ -23,27 +23,26 @@ use prost::EncodeError as ProtoBufEncodeError; use futures::{Poll, Future, Stream}; 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::dev::{HttpResponseBuilder, Payload}; use actix_web::error::{Error, PayloadError, ResponseError}; - -#[derive(Fail, Debug)] +#[derive(Debug, Display)] pub enum ProtoBufPayloadError { /// Payload size is bigger than 256k - #[fail(display="Payload size is bigger than 256k")] + #[display(fmt="Payload size is bigger than 256k")] Overflow, /// Content type error - #[fail(display="Content type error")] + #[display(fmt="Content type error")] ContentType, /// Serialize error - #[fail(display="ProtoBuf serialize error: {}", _0)] - Serialize(#[cause] ProtoBufEncodeError), + #[display(fmt="ProtoBuf serialize error: {}", _0)] + Serialize(ProtoBufEncodeError), /// Deserialize error - #[fail(display="ProtoBuf deserialize error: {}", _0)] - Deserialize(#[cause] ProtoBufDecodeError), + #[display(fmt="ProtoBuf deserialize error: {}", _0)] + Deserialize(ProtoBufDecodeError), /// Payload error - #[fail(display="Error that occur during reading payload: {}", _0)] - Payload(#[cause] PayloadError), + #[display(fmt="Error that occur during reading payload: {}", _0)] + Payload(PayloadError), } impl ResponseError for ProtoBufPayloadError { @@ -115,27 +114,31 @@ impl Default for ProtoBufConfig { } } -impl FromRequest for ProtoBuf - where T: Message + Default + 'static, S: 'static +impl FromRequest for ProtoBuf + where T: Message + Default + 'static { type Config = ProtoBufConfig; - type Result = Box>; + type Error = Error; + type Future = Box>; #[inline] - fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { + let limit = req.app_data::().map(|c| c.limit).unwrap_or(262_144); Box::new( - ProtoBufMessage::new(req) - .limit(cfg.limit) - .from_err() + ProtoBufMessage::new(req, payload) + .limit(limit) + .map_err(move |e| { + e.into() + }) .map(ProtoBuf)) } } impl Responder for ProtoBuf { - type Item = HttpResponse; type Error = Error; + type Future = Result; - fn respond_to(self, _: &HttpRequest) -> Result { + fn respond_to(self, _: &HttpRequest) -> Self::Future { let mut buf = Vec::new(); self.0.encode(&mut buf) .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) @@ -147,18 +150,18 @@ impl Responder for ProtoBuf { } } -pub struct ProtoBufMessage{ +pub struct ProtoBufMessage{ limit: usize, length: Option, - stream: Option, + stream: Option, err: Option, - fut: Option>>, + fut: Option>>, } -impl ProtoBufMessage { +impl ProtoBufMessage { /// Create `ProtoBufMessage` for request. - pub fn new(req: &T) -> Self { + pub fn new(req: &HttpRequest, payload: &mut Payload) -> Self { if req.content_type() != "application/protobuf" { return ProtoBufMessage { limit: 262_144, @@ -181,7 +184,7 @@ impl ProtoBufMessage { ProtoBufMessage { limit: 262_144, length: len, - stream: Some(req.payload()), + stream: Some(payload.take()), fut: None, err: None, } @@ -194,13 +197,12 @@ impl ProtoBufMessage { } } -impl Future for ProtoBufMessage -where T: HttpMessage + 'static +impl Future for ProtoBufMessage { - type Item = U; + type Item = T; type Error = ProtoBufPayloadError; - fn poll(&mut self) -> Poll { + fn poll(&mut self) -> Poll { if let Some(ref mut fut) = self.fut { return fut.poll(); } @@ -228,7 +230,7 @@ where T: HttpMessage + 'static body.extend_from_slice(&chunk); Ok(body) } - }).and_then(|body| Ok(::decode(&mut body.into_buf())?)); + }).and_then(|body| Ok(::decode(&mut body.into_buf())?)); self.fut = Some(Box::new(fut)); self.poll() } @@ -251,30 +253,11 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder { } } - - -pub trait ProtoBufHttpMessage { - fn protobuf(&self) -> ProtoBufMessage - where Self: HttpMessage + 'static; -} - -impl ProtoBufHttpMessage for HttpRequest { - - #[inline] - fn protobuf(&self) -> ProtoBufMessage - where Self: HttpMessage + 'static - { - ProtoBufMessage::new(self) - } -} - - - #[cfg(test)] mod tests { use super::*; use http::header; - use actix_web::test::TestRequest; + use actix_web::test::{block_on, TestRequest}; impl PartialEq for ProtoBufPayloadError { fn eq(&self, other: &ProtoBufPayloadError) -> bool { @@ -303,33 +286,34 @@ mod tests { #[test] fn test_protobuf() { let protobuf = ProtoBuf(MyObject{number: 9 , name: "test".to_owned()}); - let resp = protobuf.respond_to(&TestRequest::default().finish()).unwrap(); + let req = TestRequest::default().to_http_request(); + let resp = protobuf.respond_to(&req).unwrap(); assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf"); } #[test] fn test_protobuf_message() { - let req = TestRequest::default().finish(); - let mut protobuf = req.protobuf::(); - assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); + let (req, mut pl) = TestRequest::default().to_http_parts(); + let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl)); + assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); - let req = TestRequest::default() + let (req, mut pl) = TestRequest::default() .header( header::CONTENT_TYPE, header::HeaderValue::from_static("application/text"), - ).finish(); - let mut protobuf = req.protobuf::(); - assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::ContentType); + ).to_http_parts(); + let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl)); + assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); - let req = TestRequest::default() + let (req, mut pl) = TestRequest::default() .header( header::CONTENT_TYPE, header::HeaderValue::from_static("application/protobuf"), ).header( header::CONTENT_LENGTH, header::HeaderValue::from_static("10000"), - ).finish(); - let mut protobuf = req.protobuf::().limit(100); - assert_eq!(protobuf.poll().err().unwrap(), ProtoBufPayloadError::Overflow); + ).to_http_parts(); + let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl).limit(100)); + assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::Overflow); } } From 90648058b458705bb5caa22e0e6037cd1ae9cb96 Mon Sep 17 00:00:00 2001 From: Stefan Puhlmann Date: Sat, 18 May 2019 14:36:36 +0200 Subject: [PATCH 18/35] updating example --- examples/prost-example/client.py | 10 +++++----- examples/prost-example/src/main.rs | 32 +++++++++++++++--------------- 2 files changed, 21 insertions(+), 21 deletions(-) mode change 100644 => 100755 examples/prost-example/client.py diff --git a/examples/prost-example/client.py b/examples/prost-example/client.py old mode 100644 new mode 100755 index c55f78885..1f16270f4 --- a/examples/prost-example/client.py +++ b/examples/prost-example/client.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # just start server and run client.py # wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-python-3.5.1.zip @@ -5,12 +6,11 @@ # cd protobuf-3.5.1/python/ # python3.6 setup.py install -# pip3.6 install --upgrade pip -# pip3.6 install aiohttp +# pip3 install --upgrade pip +# pip3 install aiohttp -# python3.6 client.py +# python3 client.py -#!/usr/bin/env python import test_pb2 import traceback import sys @@ -48,7 +48,7 @@ async def fetch(session): obj = test_pb2.MyObj() obj.number = 9 obj.name = 'USB' - async with session.post('http://localhost:8080/', data=obj.SerializeToString(), + async with session.post('http://127.0.0.1:8081/', data=obj.SerializeToString(), headers={"content-type": "application/protobuf"}) as resp: print(resp.status) data = await resp.read() diff --git a/examples/prost-example/src/main.rs b/examples/prost-example/src/main.rs index d61ea1402..15f7f4c88 100644 --- a/examples/prost-example/src/main.rs +++ b/examples/prost-example/src/main.rs @@ -1,43 +1,43 @@ -extern crate bytes; extern crate actix; -extern crate actix_web; extern crate actix_protobuf; +extern crate actix_web; +extern crate bytes; extern crate env_logger; extern crate prost; -#[macro_use] +#[macro_use] extern crate prost_derive; -use actix_web::*; use actix_protobuf::*; +use actix_web::*; #[derive(Clone, PartialEq, Message)] pub struct MyObj { - #[prost(int32, tag="1")] + #[prost(int32, tag = "1")] pub number: i32, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub name: String, } - fn index(msg: ProtoBuf) -> Result { println!("model: {:?}", msg); - HttpResponse::Ok().protobuf(msg.0) // <- send response + HttpResponse::Ok().protobuf(msg.0) // <- send response } - fn main() { ::std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); let sys = actix::System::new("prost-example"); - server::new(|| { + HttpServer::new(|| { App::new() - .middleware(middleware::Logger::default()) - .resource("/", |r| r.method(http::Method::POST).with(index))}) - .bind("127.0.0.1:8080").unwrap() - .shutdown_timeout(1) - .start(); + .wrap(middleware::Logger::default()) + .service(web::resource("/").route(web::post().to(index))) + }) + .bind("127.0.0.1:8081") + .unwrap() + .shutdown_timeout(1) + .start(); - println!("Started http server: 127.0.0.1:8080"); + println!("Started http server: 127.0.0.1:8081"); let _ = sys.run(); } From 99e70db94bab2e5dd18d1bb3bcbe9886c46c598c Mon Sep 17 00:00:00 2001 From: Stefan Puhlmann Date: Sat, 18 May 2019 19:29:09 +0200 Subject: [PATCH 19/35] updating actix-web version and removing travil config --- .travis.yml | 1 - Cargo.toml | 2 +- examples/prost-example/Cargo.toml | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32fe873ae..5ac82ea72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: rust rust: - - 1.21.0 - stable - beta - nightly diff --git a/Cargo.toml b/Cargo.toml index f0770489c..f277ef9ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ futures = "0.1" derive_more = "0.14" actix = "0.8.1" -actix-web = "1.0.0-b3" +actix-web = "1.0.0-beta.5" prost = "0.4" diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index 18a6ffc8f..e04f1bb11 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -11,5 +11,5 @@ prost = "0.4" prost-derive = "0.4" actix = "0.8.1" -actix-web = "1.0.0-b3" +actix-web = "1.0.0-beta.5" actix-protobuf = { path="../../" } \ No newline at end of file From 34f48cd24ab835450afbd08b055b3d167d9d9356 Mon Sep 17 00:00:00 2001 From: Stefan Puhlmann Date: Sat, 18 May 2019 22:30:52 +0200 Subject: [PATCH 20/35] bumping version to 0.4.0 --- CHANGES.md | 5 +++++ Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e631f811d..fbda1fc15 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # Changes +## 0.4.0 (2019-05-18) + +* Upgrade to actix-web 1.0.0-beta5 +* Removed `protobuf` method for `HttpRequest` (use `ProtoBuf` extractor instead) + ## 0.3.0 (2019-03-07) * Upgrade to actix-web 0.7.18 diff --git a/Cargo.toml b/Cargo.toml index f277ef9ba..3dd3ab39a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-protobuf" -version = "0.3.0" +version = "0.4.0" authors = ["kingxsp "] description = "Protobuf support for actix-web framework." readme = "README.md" From f438f80d127129800f6e20cd93e2f132f142b944 Mon Sep 17 00:00:00 2001 From: Stefan Puhlmann Date: Sun, 19 May 2019 00:05:33 +0200 Subject: [PATCH 21/35] bumping to actix-web 1.0.0-rc --- CHANGES.md | 2 +- Cargo.toml | 2 +- examples/prost-example/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fbda1fc15..74b18c7dd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,7 @@ ## 0.4.0 (2019-05-18) -* Upgrade to actix-web 1.0.0-beta5 +* Upgrade to actix-web 1.0.0-rc * Removed `protobuf` method for `HttpRequest` (use `ProtoBuf` extractor instead) ## 0.3.0 (2019-03-07) diff --git a/Cargo.toml b/Cargo.toml index 3dd3ab39a..67475cf8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ futures = "0.1" derive_more = "0.14" actix = "0.8.1" -actix-web = "1.0.0-beta.5" +actix-web = "1.0.0-rc" prost = "0.4" diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index e04f1bb11..ef4156049 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -11,5 +11,5 @@ prost = "0.4" prost-derive = "0.4" actix = "0.8.1" -actix-web = "1.0.0-beta.5" +actix-web = "1.0.0-rc" actix-protobuf = { path="../../" } \ No newline at end of file From bf34d11a49ec8e12b3d098853a80b7df7bde25de Mon Sep 17 00:00:00 2001 From: Stefan Puhlmann Date: Tue, 21 May 2019 21:39:48 +0200 Subject: [PATCH 22/35] Normalizing code formatting based on actix-web style --- examples/prost-example/src/main.rs | 3 +- rustfmt.toml | 2 + src/lib.rs | 119 ++++++++++++++++------------- 3 files changed, 69 insertions(+), 55 deletions(-) create mode 100644 rustfmt.toml diff --git a/examples/prost-example/src/main.rs b/examples/prost-example/src/main.rs index 15f7f4c88..5f1029b7e 100644 --- a/examples/prost-example/src/main.rs +++ b/examples/prost-example/src/main.rs @@ -32,8 +32,7 @@ fn main() { App::new() .wrap(middleware::Logger::default()) .service(web::resource("/").route(web::post().to(index))) - }) - .bind("127.0.0.1:8081") + }).bind("127.0.0.1:8081") .unwrap() .shutdown_timeout(1) .start(); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..94bd11d51 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +max_width = 89 +reorder_imports = true diff --git a/src/lib.rs b/src/lib.rs index 7c0811879..5e23d5b05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,52 +1,52 @@ extern crate actix; extern crate actix_web; extern crate bytes; -extern crate futures; extern crate derive_more; +extern crate futures; #[cfg(test)] extern crate http; extern crate prost; #[cfg(test)] -#[macro_use] extern crate prost_derive; +#[macro_use] +extern crate prost_derive; -use std::fmt; use derive_more::Display; +use std::fmt; use std::ops::{Deref, DerefMut}; use bytes::{BytesMut, IntoBuf}; -use prost::Message; use prost::DecodeError as ProtoBufDecodeError; use prost::EncodeError as ProtoBufEncodeError; +use prost::Message; -use futures::{Poll, Future, Stream}; -use actix_web::http::header::{CONTENT_TYPE, CONTENT_LENGTH}; -use actix_web::{Responder, HttpMessage, HttpRequest, HttpResponse, FromRequest}; use actix_web::dev::{HttpResponseBuilder, Payload}; use actix_web::error::{Error, PayloadError, ResponseError}; +use actix_web::http::header::{CONTENT_LENGTH, CONTENT_TYPE}; +use actix_web::{FromRequest, HttpMessage, HttpRequest, HttpResponse, Responder}; +use futures::{Future, Poll, Stream}; #[derive(Debug, Display)] pub enum ProtoBufPayloadError { /// Payload size is bigger than 256k - #[display(fmt="Payload size is bigger than 256k")] + #[display(fmt = "Payload size is bigger than 256k")] Overflow, /// Content type error - #[display(fmt="Content type error")] + #[display(fmt = "Content type error")] ContentType, /// Serialize error - #[display(fmt="ProtoBuf serialize error: {}", _0)] + #[display(fmt = "ProtoBuf serialize error: {}", _0)] Serialize(ProtoBufEncodeError), /// Deserialize error - #[display(fmt="ProtoBuf deserialize error: {}", _0)] + #[display(fmt = "ProtoBuf deserialize error: {}", _0)] Deserialize(ProtoBufDecodeError), /// Payload error - #[display(fmt="Error that occur during reading payload: {}", _0)] + #[display(fmt = "Error that occur during reading payload: {}", _0)] Payload(PayloadError), } impl ResponseError for ProtoBufPayloadError { - fn error_response(&self) -> HttpResponse { match *self { ProtoBufPayloadError::Overflow => HttpResponse::PayloadTooLarge().into(), @@ -83,13 +83,19 @@ impl DerefMut for ProtoBuf { } } -impl fmt::Debug for ProtoBuf where T: fmt::Debug { +impl fmt::Debug for ProtoBuf +where + T: fmt::Debug, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ProtoBuf: {:?}", self.0) } } -impl fmt::Display for ProtoBuf where T: fmt::Display { +impl fmt::Display for ProtoBuf +where + T: fmt::Display, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } @@ -100,7 +106,6 @@ pub struct ProtoBufConfig { } 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; @@ -110,27 +115,30 @@ impl ProtoBufConfig { impl Default for ProtoBufConfig { fn default() -> Self { - ProtoBufConfig{limit: 262_144} + ProtoBufConfig { limit: 262_144 } } } impl FromRequest for ProtoBuf - where T: Message + Default + 'static +where + T: Message + Default + 'static, { type Config = ProtoBufConfig; type Error = Error; - type Future = Box>; + type Future = Box>; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { - let limit = req.app_data::().map(|c| c.limit).unwrap_or(262_144); + let limit = req + .app_data::() + .map(|c| c.limit) + .unwrap_or(262_144); Box::new( ProtoBufMessage::new(req, payload) .limit(limit) - .map_err(move |e| { - e.into() - }) - .map(ProtoBuf)) + .map_err(move |e| e.into()) + .map(ProtoBuf), + ) } } @@ -140,26 +148,26 @@ impl Responder for ProtoBuf { fn respond_to(self, _: &HttpRequest) -> Self::Future { let mut buf = Vec::new(); - self.0.encode(&mut buf) + self.0 + .encode(&mut buf) .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) .and_then(|()| { Ok(HttpResponse::Ok() - .content_type("application/protobuf") - .body(buf)) + .content_type("application/protobuf") + .body(buf)) }) } } -pub struct ProtoBufMessage{ +pub struct ProtoBufMessage { limit: usize, length: Option, stream: Option, err: Option, - fut: Option>>, + fut: Option>>, } impl ProtoBufMessage { - /// Create `ProtoBufMessage` for request. pub fn new(req: &HttpRequest, payload: &mut Payload) -> Self { if req.content_type() != "application/protobuf" { @@ -197,8 +205,7 @@ impl ProtoBufMessage { } } -impl Future for ProtoBufMessage -{ +impl Future for ProtoBufMessage { type Item = T; type Error = ProtoBufPayloadError; @@ -236,19 +243,18 @@ impl Future for ProtoBufMessage } } - pub trait ProtoBufResponseBuilder { - fn protobuf(&mut self, value: T) -> Result; } impl ProtoBufResponseBuilder for HttpResponseBuilder { - fn protobuf(&mut self, value: T) -> Result { self.header(CONTENT_TYPE, "application/protobuf"); 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)) } } @@ -256,8 +262,8 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder { #[cfg(test)] mod tests { use super::*; - use http::header; use actix_web::test::{block_on, TestRequest}; + use http::header; impl PartialEq for ProtoBufPayloadError { fn eq(&self, other: &ProtoBufPayloadError) -> bool { @@ -277,18 +283,24 @@ mod tests { #[derive(Clone, PartialEq, Message)] pub struct MyObject { - #[prost(int32, tag="1")] + #[prost(int32, tag = "1")] pub number: i32, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub name: String, } #[test] fn test_protobuf() { - let protobuf = ProtoBuf(MyObject{number: 9 , name: "test".to_owned()}); + let protobuf = ProtoBuf(MyObject { + number: 9, + name: "test".to_owned(), + }); let req = TestRequest::default().to_http_request(); let resp = protobuf.respond_to(&req).unwrap(); - assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf"); + assert_eq!( + resp.headers().get(header::CONTENT_TYPE).unwrap(), + "application/protobuf" + ); } #[test] @@ -298,22 +310,23 @@ mod tests { assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); let (req, mut pl) = TestRequest::default() - .header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("application/text"), - ).to_http_parts(); + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/text"), + ).to_http_parts(); let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl)); assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); let (req, mut pl) = TestRequest::default() - .header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("application/protobuf"), - ).header( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("10000"), - ).to_http_parts(); - let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl).limit(100)); + .header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("application/protobuf"), + ).header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("10000"), + ).to_http_parts(); + let protobuf = + block_on(ProtoBufMessage::::new(&req, &mut pl).limit(100)); assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::Overflow); } } From 8f7f190783bbdc93c74c313c4e8ba3056e6d03d4 Mon Sep 17 00:00:00 2001 From: Kurian Thampy Date: Tue, 1 Oct 2019 13:54:26 +0530 Subject: [PATCH 23/35] Upgrade to `prost-0.5.0` and `prost-derive-0.5.0` --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67475cf8e..a7220591d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,11 +26,11 @@ derive_more = "0.14" actix = "0.8.1" actix-web = "1.0.0-rc" -prost = "0.4" +prost = "0.5.0" [dev-dependencies] http = "^0.1" -prost-derive = "^0.4" +prost-derive = "0.5.0" [workspace] members = [ From 62e9d32b3efca68d5fcf0fea5c53aacb5fe0358a Mon Sep 17 00:00:00 2001 From: Kurian Thampy Date: Tue, 1 Oct 2019 13:58:06 +0530 Subject: [PATCH 24/35] Changed to `Box>` to remove warning --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5e23d5b05..f8bb3317a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,7 +125,7 @@ where { type Config = ProtoBufConfig; type Error = Error; - type Future = Box>; + type Future = Box>; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { @@ -164,7 +164,7 @@ pub struct ProtoBufMessage { length: Option, stream: Option, err: Option, - fut: Option>>, + fut: Option>>, } impl ProtoBufMessage { From 7fb3024ee28307df91a89b15814007998cda894c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 3 Oct 2019 19:12:13 +0900 Subject: [PATCH 25/35] prepare new release --- CHANGES.md | 4 ++++ Cargo.toml | 2 +- examples/prost-example/Cargo.toml | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 74b18c7dd..4702f335e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## 0.4.1 (2019-10-03) + +* Upgrade prost and prost-derive to 0.5.0 + ## 0.4.0 (2019-05-18) * Upgrade to actix-web 1.0.0-rc diff --git a/Cargo.toml b/Cargo.toml index a7220591d..3a931f218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-protobuf" -version = "0.4.0" +version = "0.4.1" authors = ["kingxsp "] description = "Protobuf support for actix-web framework." readme = "README.md" diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index ef4156049..977c17a3f 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -7,9 +7,9 @@ authors = ["kingxsp "] bytes = "0.4" env_logger = "*" -prost = "0.4" -prost-derive = "0.4" +prost = "0.5.0" +prost-derive = "0.5.0" actix = "0.8.1" actix-web = "1.0.0-rc" -actix-protobuf = { path="../../" } \ No newline at end of file +actix-protobuf = { path="../../" } From 342c711bad3b1ad45c4bc24d9a6430cf242e5041 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 2 Jan 2020 01:04:00 +0900 Subject: [PATCH 26/35] Make crate 2018 edition --- Cargo.toml | 1 + src/lib.rs | 14 -------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3a931f218..f2e1bb7ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "actix-protobuf" version = "0.4.1" +edition = "2018" authors = ["kingxsp "] description = "Protobuf support for actix-web framework." readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index f8bb3317a..ee6648242 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,3 @@ -extern crate actix; -extern crate actix_web; -extern crate bytes; -extern crate derive_more; -extern crate futures; - -#[cfg(test)] -extern crate http; - -extern crate prost; -#[cfg(test)] -#[macro_use] -extern crate prost_derive; - use derive_more::Display; use std::fmt; use std::ops::{Deref, DerefMut}; From 0eeda4c39878e0f7c2deb6b8376da4fe9014eabd Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 2 Jan 2020 03:40:29 +0900 Subject: [PATCH 27/35] Migrate to actix-web v2 --- Cargo.toml | 12 ++-- examples/prost-example/Cargo.toml | 10 +-- examples/prost-example/src/main.rs | 24 +++---- src/lib.rs | 106 ++++++++++++++++------------- 4 files changed, 77 insertions(+), 75 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f2e1bb7ba..c12834838 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "actix-protobuf" version = "0.4.1" edition = "2018" -authors = ["kingxsp "] +authors = ["kingxsp , Yuki Okushi "] description = "Protobuf support for actix-web framework." readme = "README.md" keywords = ["actix"] @@ -21,16 +21,16 @@ path = "src/lib.rs" [dependencies] bytes = "0.4" -futures = "0.1" -derive_more = "0.14" +futures = "0.3.1" +derive_more = "0.99" -actix = "0.8.1" -actix-web = "1.0.0-rc" +actix = "0.9" +actix-rt = "1" +actix-web = "2" prost = "0.5.0" [dev-dependencies] -http = "^0.1" prost-derive = "0.5.0" [workspace] diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index 977c17a3f..555b74913 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "prost-example" -version = "0.3.0" -authors = ["kingxsp "] +version = "0.4.0" +edition = "2018" +authors = ["kingxsp , Yuki Okushi "] [dependencies] bytes = "0.4" @@ -10,6 +11,7 @@ env_logger = "*" prost = "0.5.0" prost-derive = "0.5.0" -actix = "0.8.1" -actix-web = "1.0.0-rc" +actix = "0.9" +actix-rt = "1" +actix-web = "2" actix-protobuf = { path="../../" } diff --git a/examples/prost-example/src/main.rs b/examples/prost-example/src/main.rs index 5f1029b7e..61dd729c9 100644 --- a/examples/prost-example/src/main.rs +++ b/examples/prost-example/src/main.rs @@ -1,9 +1,3 @@ -extern crate actix; -extern crate actix_protobuf; -extern crate actix_web; -extern crate bytes; -extern crate env_logger; -extern crate prost; #[macro_use] extern crate prost_derive; @@ -18,25 +12,23 @@ pub struct MyObj { pub name: String, } -fn index(msg: ProtoBuf) -> Result { +async fn index(msg: ProtoBuf) -> Result { println!("model: {:?}", msg); HttpResponse::Ok().protobuf(msg.0) // <- send response } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +#[actix_rt::main] +async fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=debug,actix_server=info"); env_logger::init(); - let sys = actix::System::new("prost-example"); HttpServer::new(|| { App::new() .wrap(middleware::Logger::default()) .service(web::resource("/").route(web::post().to(index))) - }).bind("127.0.0.1:8081") - .unwrap() + }) + .bind("127.0.0.1:8081")? .shutdown_timeout(1) - .start(); - - println!("Started http server: 127.0.0.1:8081"); - let _ = sys.run(); + .run() + .await } diff --git a/src/lib.rs b/src/lib.rs index ee6648242..3199bb54f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,10 @@ use derive_more::Display; use std::fmt; use std::ops::{Deref, DerefMut}; +use std::pin::Pin; +use std::future::Future; +use std::task; +use std::task::Poll; use bytes::{BytesMut, IntoBuf}; use prost::DecodeError as ProtoBufDecodeError; @@ -11,7 +15,8 @@ use actix_web::dev::{HttpResponseBuilder, Payload}; use actix_web::error::{Error, PayloadError, ResponseError}; use actix_web::http::header::{CONTENT_LENGTH, CONTENT_TYPE}; use actix_web::{FromRequest, HttpMessage, HttpRequest, HttpResponse, Responder}; -use futures::{Future, Poll, Stream}; +use futures::future::{ready, LocalBoxFuture, FutureExt, Ready}; +use futures::StreamExt; #[derive(Debug, Display)] pub enum ProtoBufPayloadError { @@ -111,7 +116,7 @@ where { type Config = ProtoBufConfig; type Error = Error; - type Future = Box>; + type Future = LocalBoxFuture<'static, Result>; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { @@ -119,29 +124,30 @@ where .app_data::() .map(|c| c.limit) .unwrap_or(262_144); - Box::new( - ProtoBufMessage::new(req, payload) - .limit(limit) - .map_err(move |e| e.into()) - .map(ProtoBuf), - ) + ProtoBufMessage::new(req, payload) + .limit(limit) + .map(move |res| match res { + Err(e) => Err(e.into()), + Ok(item) => Ok(ProtoBuf(item)), + }) + .boxed_local() } } impl Responder for ProtoBuf { type Error = Error; - type Future = Result; + type Future = Ready>; fn respond_to(self, _: &HttpRequest) -> Self::Future { let mut buf = Vec::new(); - self.0 + ready(self.0 .encode(&mut buf) .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) .and_then(|()| { Ok(HttpResponse::Ok() .content_type("application/protobuf") .body(buf)) - }) + })) } } @@ -150,7 +156,7 @@ pub struct ProtoBufMessage { length: Option, stream: Option, err: Option, - fut: Option>>, + fut: Option>>, } impl ProtoBufMessage { @@ -192,40 +198,44 @@ impl ProtoBufMessage { } impl Future for ProtoBufMessage { - type Item = T; - type Error = ProtoBufPayloadError; + type Output = Result; - fn poll(&mut self) -> Poll { + fn poll(mut self: Pin<&mut Self>, task: &mut task::Context<'_>) -> Poll { if let Some(ref mut fut) = self.fut { - return fut.poll(); + return Pin::new(fut).poll(task); } if let Some(err) = self.err.take() { - return Err(err); + return Poll::Ready(Err(err)); } let limit = self.limit; if let Some(len) = self.length.take() { if len > limit { - return Err(ProtoBufPayloadError::Overflow); + return Poll::Ready(Err(ProtoBufPayloadError::Overflow)); } } - let fut = self - .stream - .take() - .expect("ProtoBufMessage could not be used second time") - .from_err() - .fold(BytesMut::with_capacity(8192), move |mut body, chunk| { - if (body.len() + chunk.len()) > limit { - Err(ProtoBufPayloadError::Overflow) - } else { - body.extend_from_slice(&chunk); - Ok(body) + let mut stream = self.stream.take().expect("ProtoBufMessage could not be used second time"); + + self.fut = Some( + async move { + let mut body = BytesMut::with_capacity(8192); + + while let Some(item) = stream.next().await { + let chunk = item?; + if (body.len() + chunk.len()) > limit { + return Err(ProtoBufPayloadError::Overflow); + } else { + body.extend_from_slice(&chunk); + } } - }).and_then(|body| Ok(::decode(&mut body.into_buf())?)); - self.fut = Some(Box::new(fut)); - self.poll() + + return Ok(::decode(&mut body.into_buf())?); + } + .boxed_local(), + ); + self.poll(task) } } @@ -248,8 +258,8 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder { #[cfg(test)] mod tests { use super::*; - use actix_web::test::{block_on, TestRequest}; - use http::header; + use actix_web::test::TestRequest; + use actix_web::http::header; impl PartialEq for ProtoBufPayloadError { fn eq(&self, other: &ProtoBufPayloadError) -> bool { @@ -275,44 +285,42 @@ mod tests { pub name: String, } - #[test] - fn test_protobuf() { + #[actix_rt::test] + async fn test_protobuf() { let protobuf = ProtoBuf(MyObject { number: 9, name: "test".to_owned(), }); let req = TestRequest::default().to_http_request(); - let resp = protobuf.respond_to(&req).unwrap(); + let resp = protobuf.respond_to(&req).await.unwrap(); assert_eq!( resp.headers().get(header::CONTENT_TYPE).unwrap(), "application/protobuf" ); } - #[test] - fn test_protobuf_message() { + #[actix_rt::test] + async fn test_protobuf_message() { let (req, mut pl) = TestRequest::default().to_http_parts(); - let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl)); + let protobuf = ProtoBufMessage::::new(&req, &mut pl).await; assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); - let (req, mut pl) = TestRequest::default() - .header( + let (req, mut pl) = TestRequest::with_header( header::CONTENT_TYPE, - header::HeaderValue::from_static("application/text"), + "application/text", ).to_http_parts(); - let protobuf = block_on(ProtoBufMessage::::new(&req, &mut pl)); + let protobuf = ProtoBufMessage::::new(&req, &mut pl).await; assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); - let (req, mut pl) = TestRequest::default() - .header( + let (req, mut pl) = TestRequest::with_header( header::CONTENT_TYPE, - header::HeaderValue::from_static("application/protobuf"), + "application/protobuf", ).header( header::CONTENT_LENGTH, - header::HeaderValue::from_static("10000"), + "10000", ).to_http_parts(); let protobuf = - block_on(ProtoBufMessage::::new(&req, &mut pl).limit(100)); + ProtoBufMessage::::new(&req, &mut pl).limit(100).await; assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::Overflow); } } From fe2553474e77c467a0cdf0c9349684bffd4a34da Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 2 Jan 2020 04:22:52 +0900 Subject: [PATCH 28/35] Run rustfmt --- src/lib.rs | 57 +++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3199bb54f..b82795e61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,8 @@ use derive_more::Display; use std::fmt; +use std::future::Future; use std::ops::{Deref, DerefMut}; use std::pin::Pin; -use std::future::Future; use std::task; use std::task::Poll; @@ -15,7 +15,7 @@ use actix_web::dev::{HttpResponseBuilder, Payload}; use actix_web::error::{Error, PayloadError, ResponseError}; use actix_web::http::header::{CONTENT_LENGTH, CONTENT_TYPE}; use actix_web::{FromRequest, HttpMessage, HttpRequest, HttpResponse, Responder}; -use futures::future::{ready, LocalBoxFuture, FutureExt, Ready}; +use futures::future::{ready, FutureExt, LocalBoxFuture, Ready}; use futures::StreamExt; #[derive(Debug, Display)] @@ -140,14 +140,16 @@ impl Responder for ProtoBuf { fn respond_to(self, _: &HttpRequest) -> Self::Future { let mut buf = Vec::new(); - ready(self.0 - .encode(&mut buf) - .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) - .and_then(|()| { - Ok(HttpResponse::Ok() - .content_type("application/protobuf") - .body(buf)) - })) + ready( + self.0 + .encode(&mut buf) + .map_err(|e| Error::from(ProtoBufPayloadError::Serialize(e))) + .and_then(|()| { + Ok(HttpResponse::Ok() + .content_type("application/protobuf") + .body(buf)) + }), + ) } } @@ -200,7 +202,10 @@ impl ProtoBufMessage { impl Future for ProtoBufMessage { type Output = Result; - fn poll(mut self: Pin<&mut Self>, task: &mut task::Context<'_>) -> Poll { + fn poll( + mut self: Pin<&mut Self>, + task: &mut task::Context<'_>, + ) -> Poll { if let Some(ref mut fut) = self.fut { return Pin::new(fut).poll(task); } @@ -216,7 +221,10 @@ impl Future for ProtoBufMessage { } } - let mut stream = self.stream.take().expect("ProtoBufMessage could not be used second time"); + let mut stream = self + .stream + .take() + .expect("ProtoBufMessage could not be used second time"); self.fut = Some( async move { @@ -258,8 +266,8 @@ impl ProtoBufResponseBuilder for HttpResponseBuilder { #[cfg(test)] mod tests { use super::*; - use actix_web::test::TestRequest; use actix_web::http::header; + use actix_web::test::TestRequest; impl PartialEq for ProtoBufPayloadError { fn eq(&self, other: &ProtoBufPayloadError) -> bool { @@ -305,22 +313,19 @@ mod tests { let protobuf = ProtoBufMessage::::new(&req, &mut pl).await; assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/text", - ).to_http_parts(); + let (req, mut pl) = + TestRequest::with_header(header::CONTENT_TYPE, "application/text") + .to_http_parts(); let protobuf = ProtoBufMessage::::new(&req, &mut pl).await; assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::ContentType); - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/protobuf", - ).header( - header::CONTENT_LENGTH, - "10000", - ).to_http_parts(); - let protobuf = - ProtoBufMessage::::new(&req, &mut pl).limit(100).await; + let (req, mut pl) = + TestRequest::with_header(header::CONTENT_TYPE, "application/protobuf") + .header(header::CONTENT_LENGTH, "10000") + .to_http_parts(); + let protobuf = ProtoBufMessage::::new(&req, &mut pl) + .limit(100) + .await; assert_eq!(protobuf.err().unwrap(), ProtoBufPayloadError::Overflow); } } From 06a24990713b3beda8de522e17a0aaaeab30de81 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 2 Jan 2020 04:26:17 +0900 Subject: [PATCH 29/35] Update CHANGES.md --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 4702f335e..9a3aa9c0f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## 0.5.0 (in the future) + +* Migrate to actix-web 2.0.0 and std::future + ## 0.4.1 (2019-10-03) * Upgrade prost and prost-derive to 0.5.0 From d7387ca5b55ebc4e8daa396921661c0c3191ed4d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 2 Jan 2020 04:29:10 +0900 Subject: [PATCH 30/35] Tweak CI --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ac82ea72..74c230f9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ rust: - beta - nightly -sudo: required -dist: trusty +os: linux +dist: xenial env: global: @@ -26,7 +26,7 @@ addons: before_script: - | if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then - ( ( cargo install clippy && export CLIPPY=true ) || export CLIPPY=false ); + ( ( rustup component add clippy && export CLIPPY=true ) || export CLIPPY=false ); fi - export PATH=$PATH:~/.cargo/bin From fe2cc9bf4a9deb54cab5adc8b6422bef9a4a0b24 Mon Sep 17 00:00:00 2001 From: Parker Timmerman Date: Wed, 15 Jan 2020 11:48:34 -0500 Subject: [PATCH 31/35] Bump up prost to 0.6.0 (#10) --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c12834838..61280e836 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,10 +28,10 @@ actix = "0.9" actix-rt = "1" actix-web = "2" -prost = "0.5.0" +prost = "0.6.0" [dev-dependencies] -prost-derive = "0.5.0" +prost-derive = "0.6.0" [workspace] members = [ From 777990d5758ff9dd4ec0c1988a7d683cf5ddbd3b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 24 Jan 2020 15:41:57 +0900 Subject: [PATCH 32/35] Update dependencies and bump up version to 0.5 (#11) * Bump up bytes to 0.5 * Update example's dependencies * Bump up version to 0.5 --- CHANGES.md | 2 ++ Cargo.toml | 4 ++-- examples/prost-example/Cargo.toml | 8 ++++---- src/lib.rs | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9a3aa9c0f..f5de3a73f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,8 @@ ## 0.5.0 (in the future) * Migrate to actix-web 2.0.0 and std::future +* Update prost to 0.6 +* Update bytes to 0.5 ## 0.4.1 (2019-10-03) diff --git a/Cargo.toml b/Cargo.toml index 61280e836..2e87fcba7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-protobuf" -version = "0.4.1" +version = "0.5.0" edition = "2018" authors = ["kingxsp , Yuki Okushi "] description = "Protobuf support for actix-web framework." @@ -20,7 +20,7 @@ name = "actix_protobuf" path = "src/lib.rs" [dependencies] -bytes = "0.4" +bytes = "0.5" futures = "0.3.1" derive_more = "0.99" diff --git a/examples/prost-example/Cargo.toml b/examples/prost-example/Cargo.toml index 555b74913..353710bc4 100644 --- a/examples/prost-example/Cargo.toml +++ b/examples/prost-example/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "prost-example" -version = "0.4.0" +version = "0.5.0" edition = "2018" authors = ["kingxsp , Yuki Okushi "] [dependencies] -bytes = "0.4" +bytes = "0.5" env_logger = "*" -prost = "0.5.0" -prost-derive = "0.5.0" +prost = "0.6.0" +prost-derive = "0.6.0" actix = "0.9" actix-rt = "1" diff --git a/src/lib.rs b/src/lib.rs index b82795e61..c9b2f9ddd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ use std::pin::Pin; use std::task; use std::task::Poll; -use bytes::{BytesMut, IntoBuf}; +use bytes::BytesMut; use prost::DecodeError as ProtoBufDecodeError; use prost::EncodeError as ProtoBufEncodeError; use prost::Message; @@ -239,7 +239,7 @@ impl Future for ProtoBufMessage { } } - return Ok(::decode(&mut body.into_buf())?); + return Ok(::decode(&mut body)?); } .boxed_local(), ); From 71e2f682e20bf5624d9cd06762bc4d78d68f4c53 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 25 Jan 2020 02:39:32 +0900 Subject: [PATCH 33/35] Update example (#12) * Update example * Check example's build on CI * Update README --- .travis.yml | 2 +- README.md | 16 +++++++++------- examples/prost-example/client.py | 8 ++++---- examples/prost-example/test_pb2.py | 25 ++++++++++++------------- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 74c230f9e..848e4421d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ script: if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then USE_SKEPTIC=1 cargo test else - cargo test + cargo test && cargo check --examples fi - | if [[ "$TRAVIS_RUST_VERSION" == "nightly" && $CLIPPY ]]; then diff --git a/README.md b/README.md index e5d824d70..0c53a7822 100644 --- a/README.md +++ b/README.md @@ -6,23 +6,25 @@ Protobuf support for actix-web framework. ## Example ```rust,ignore -use actix_web::{HttpResponse, Result}; -use actix_protobuf::ProtoBuf; +use actix_protobuf::*; +use actix_web::*; -#[derive(Clone, Debug, PartialEq, Message)] +#[derive(Clone, PartialEq, Message)] pub struct MyObj { - #[prost(int32, tag="1")] + #[prost(int32, tag = "1")] pub number: i32, - #[prost(string, tag="2")] + #[prost(string, tag = "2")] pub name: String, } -fn index(msg: ProtoBuf) -> Result { +async fn index(msg: ProtoBuf) -> Result { println!("model: {:?}", msg); - HttpResponse::Ok().protobuf(msg.0) // <- send response + HttpResponse::Ok().protobuf(msg.0) // <- send response } ``` +See [here](https://github.com/actix/actix-protobuf/tree/master/examples/prost-example) for the complete example. + ## License This project is licensed under either of diff --git a/examples/prost-example/client.py b/examples/prost-example/client.py index 1f16270f4..939a71b5d 100755 --- a/examples/prost-example/client.py +++ b/examples/prost-example/client.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 # just start server and run client.py -# wget https://github.com/google/protobuf/releases/download/v3.5.1/protobuf-python-3.5.1.zip -# unzip protobuf-python-3.5.1.zip.1 -# cd protobuf-3.5.1/python/ -# python3.6 setup.py install +# wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protobuf-python-3.11.2.zip +# unzip protobuf-python-3.11.2.zip.1 +# cd protobuf-3.11.2/python/ +# python3 setup.py install # pip3 install --upgrade pip # pip3 install aiohttp diff --git a/examples/prost-example/test_pb2.py b/examples/prost-example/test_pb2.py index 05e71f3a6..ea5a1d9d6 100644 --- a/examples/prost-example/test_pb2.py +++ b/examples/prost-example/test_pb2.py @@ -1,13 +1,11 @@ +# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: test.proto -import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -19,9 +17,9 @@ DESCRIPTOR = _descriptor.FileDescriptor( name='test.proto', package='', syntax='proto3', - serialized_pb=_b('\n\ntest.proto\"%\n\x05MyObj\x12\x0e\n\x06number\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\tb\x06proto3') + serialized_options=None, + serialized_pb=b'\n\ntest.proto\"%\n\x05MyObj\x12\x0e\n\x06number\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\tb\x06proto3' ) -_sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -39,21 +37,21 @@ _MYOBJ = _descriptor.Descriptor( has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='name', full_name='MyObj.name', index=1, number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - options=None), + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], nested_types=[], enum_types=[ ], - options=None, + serialized_options=None, is_extendable=False, syntax='proto3', extension_ranges=[], @@ -64,12 +62,13 @@ _MYOBJ = _descriptor.Descriptor( ) DESCRIPTOR.message_types_by_name['MyObj'] = _MYOBJ +_sym_db.RegisterFileDescriptor(DESCRIPTOR) -MyObj = _reflection.GeneratedProtocolMessageType('MyObj', (_message.Message,), dict( - DESCRIPTOR = _MYOBJ, - __module__ = 'test_pb2' +MyObj = _reflection.GeneratedProtocolMessageType('MyObj', (_message.Message,), { + 'DESCRIPTOR' : _MYOBJ, + '__module__' : 'test_pb2' # @@protoc_insertion_point(class_scope:MyObj) - )) + }) _sym_db.RegisterMessage(MyObj) From 3ed6519c0c2f21bbbf7171e9d699e762958d494c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 25 Jan 2020 02:45:24 +0900 Subject: [PATCH 34/35] Update changelog (#13) --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index f5de3a73f..dc2ec68bf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## 0.5.0 (in the future) +## 0.5.0 (2019-01-24) * Migrate to actix-web 2.0.0 and std::future * Update prost to 0.6 From dbd52a48a468076da0911281706b74dbf30307f7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 29 Jan 2020 11:36:31 +0000 Subject: [PATCH 35/35] move to own module --- .gitignore => actix-protobuf/.gitignore | 0 .travis.yml => actix-protobuf/.travis.yml | 0 CHANGES.md => actix-protobuf/CHANGES.md | 0 Cargo.toml => actix-protobuf/Cargo.toml | 0 README.md => actix-protobuf/README.md | 0 {examples => actix-protobuf/examples}/prost-example/Cargo.toml | 0 {examples => actix-protobuf/examples}/prost-example/client.py | 0 {examples => actix-protobuf/examples}/prost-example/src/main.rs | 0 {examples => actix-protobuf/examples}/prost-example/test.proto | 0 {examples => actix-protobuf/examples}/prost-example/test_pb2.py | 0 rustfmt.toml => actix-protobuf/rustfmt.toml | 0 {src => actix-protobuf/src}/lib.rs | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename .gitignore => actix-protobuf/.gitignore (100%) rename .travis.yml => actix-protobuf/.travis.yml (100%) rename CHANGES.md => actix-protobuf/CHANGES.md (100%) rename Cargo.toml => actix-protobuf/Cargo.toml (100%) rename README.md => actix-protobuf/README.md (100%) rename {examples => actix-protobuf/examples}/prost-example/Cargo.toml (100%) rename {examples => actix-protobuf/examples}/prost-example/client.py (100%) rename {examples => actix-protobuf/examples}/prost-example/src/main.rs (100%) rename {examples => actix-protobuf/examples}/prost-example/test.proto (100%) rename {examples => actix-protobuf/examples}/prost-example/test_pb2.py (100%) rename rustfmt.toml => actix-protobuf/rustfmt.toml (100%) rename {src => actix-protobuf/src}/lib.rs (100%) diff --git a/.gitignore b/actix-protobuf/.gitignore similarity index 100% rename from .gitignore rename to actix-protobuf/.gitignore diff --git a/.travis.yml b/actix-protobuf/.travis.yml similarity index 100% rename from .travis.yml rename to actix-protobuf/.travis.yml diff --git a/CHANGES.md b/actix-protobuf/CHANGES.md similarity index 100% rename from CHANGES.md rename to actix-protobuf/CHANGES.md diff --git a/Cargo.toml b/actix-protobuf/Cargo.toml similarity index 100% rename from Cargo.toml rename to actix-protobuf/Cargo.toml diff --git a/README.md b/actix-protobuf/README.md similarity index 100% rename from README.md rename to actix-protobuf/README.md diff --git a/examples/prost-example/Cargo.toml b/actix-protobuf/examples/prost-example/Cargo.toml similarity index 100% rename from examples/prost-example/Cargo.toml rename to actix-protobuf/examples/prost-example/Cargo.toml diff --git a/examples/prost-example/client.py b/actix-protobuf/examples/prost-example/client.py similarity index 100% rename from examples/prost-example/client.py rename to actix-protobuf/examples/prost-example/client.py diff --git a/examples/prost-example/src/main.rs b/actix-protobuf/examples/prost-example/src/main.rs similarity index 100% rename from examples/prost-example/src/main.rs rename to actix-protobuf/examples/prost-example/src/main.rs diff --git a/examples/prost-example/test.proto b/actix-protobuf/examples/prost-example/test.proto similarity index 100% rename from examples/prost-example/test.proto rename to actix-protobuf/examples/prost-example/test.proto diff --git a/examples/prost-example/test_pb2.py b/actix-protobuf/examples/prost-example/test_pb2.py similarity index 100% rename from examples/prost-example/test_pb2.py rename to actix-protobuf/examples/prost-example/test_pb2.py diff --git a/rustfmt.toml b/actix-protobuf/rustfmt.toml similarity index 100% rename from rustfmt.toml rename to actix-protobuf/rustfmt.toml diff --git a/src/lib.rs b/actix-protobuf/src/lib.rs similarity index 100% rename from src/lib.rs rename to actix-protobuf/src/lib.rs