1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
//! RPC framework in Rust //! //! copra is an [RPC] framework aimed at ease of use and configuration. //! It can generate most of the boilerplate code in server and client side. //! You only need to implement the core logic of services. //! //! [RPC]: https://en.wikipedia.org/wiki/Remote_procedure_call //! //! # Installation //! //! ## Protocol compiler installation //! //! `copra` uses [Protocol Buffers][protobuf] (a.k.a. protobuf) to exchange messages //! and describe service signatures. The message and service descriptions are written //! in `.proto` files, and `copra` depends on the protocol compiler to generate rust //! code from these files. //! //! Visit [this website] and download //! `proto-3.*.*-your-arch.zip` (`copra` needs protocol version 3), extract the //! `protoc` executable to a folder you like, then add `protoc` to your `PATH`. //! //! [protobuf]: https://developers.google.com/protocol-buffers/ //! [this website]: https://github.com/google/protobuf/releases //! //! ## Cargo setup //! //! Add this to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! copra = "0.1" //! futures = "0.1" //! tokio-core = "0.1" //! //! [build-dependencies] //! protoc-rust-copra = "0.1" //! ``` //! //! # Examples //! //! Here is an example of implementing an echo RPC. First, create a file named //! `echo.proto` and put it in the manifest directory (i.e. next to `Cargo.toml`). //! Populate it with: //! //! ```protobuf //! syntax = "proto3" //! //! message EchoMessage { //! string msg = 1; //! } //! //! // Our echo service contains two method. One is sending back the original string //! // directly, and the other is returning the string in reversed form. //! service Echo { //! rpc echo(EchoMessage) returns (EchoMessage); //! rpc reverse_echo(EchoMessage) returns (EchoMessage); //! } //! ``` //! //! Next, create a [`build.rs`][build-scripts] in the manifest directory, and add this to //! it: //! //! ```no_run //! extern crate protoc_rust_copra; //! //! fn main() { //! protoc_rust_copra::run(protoc_rust_copra::Args { //! out_dir: "src/protos", //! input: &["echo.proto"], //! includes: &[], //! rust_protobuf: true //! }).expect("Failed to compile proto files"); //! } //! ``` //! //! This will generate file `echo.rs` and `echo_copra.rs` in `src/protos`. //! //! Then, add this to `main.rs`: //! //! ```no_run //! extern crate copra; //! extern crate futures; //! extern crate tokio_core; //! //! use copra::{ChannelBuilder, Controller, MethodError, ServerBuilder, ServiceRegistry}; //! use futures::future::{self, Future, FutureResult}; //! use std::thread; //! use tokio_core::reactor::Core; //! //! use protos::echo::EchoMessage; //! use protos::echo_copra::{EchoRegistrant, EchoService, EchoStub}; //! //! mod protos; //! //! // Service provider must implement Clone //! #[derive(Clone)] //! struct Echo; //! //! // EchoService is a trait for defining service logic //! // It is generated by protoc-rust-copra //! impl EchoService for Echo { //! type EchoFuture = FutureResult<(EchoMessage, Controller), MethodError>; //! //! type ReverseEchoFuture = FutureResult<(EchoMessage, Controller), MethodError>; //! //! fn echo(&self, (req, ctrl): (EchoMessage, Controller)) -> Self::EchoFuture { //! let mut response = EchoMessage::new(); //! response.set_msg(req.msg); //! future::ok((response, ctrl)) //! } //! //! fn reverse_echo( //! &self, //! (req, ctrl): (EchoMessage, Controller) //! ) -> Self::ReverseEchoFuture { //! let rev: String = req.msg.chars().rev().collect(); //! let mut response = EchoMessage::new(); //! response.set_msg(rev); //! future::ok((response, ctrl)) //! } //! } //! //! fn main() { //! let addr = "127.0.0.1:8989"; //! //! // server side //! thread::spawn(move || { //! // register the service provider, so that it can be accessed //! let registrant = EchoRegistrant::new(Echo); //! let mut registry = ServiceRegistry::new(); //! registry.register_service(registrant); //! //! let server = ServerBuilder::new(addr, registry).build().unwrap(); //! server.start(); //! }); //! //! // client side //! let mut core = Core::new().unwrap(); //! let handle = core.handle(); //! let channel = core.run(ChannelBuilder::single_server(addr, handle).build()) //! .unwrap(); //! let stub = EchoStub::new(&channel); //! //! let mut request = EchoMessage::new(); //! request.set_msg("Hello world".to_string()); //! //! let (response, _info) = core.run(stub.echo(request.clone())).unwrap(); //! println!("{}", response.msg); //! //! let (response, _info) = core.run(stub.reverse_echo(request)).unwrap(); //! println!("{}", response.msg); //! } //! ``` //! //! Finally, build and run this example by executing: //! //! ```bash //! $ cargo build //! $ cargo run //! ``` //! //! [build-scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html //! //! # Note //! //! This project is still in the early development stage. It basically works, but //! you should use it with caution. #![warn(missing_docs, missing_debug_implementations)] extern crate bytes; #[macro_use] extern crate futures; extern crate httparse; #[macro_use] extern crate log; extern crate protobuf; extern crate smallvec; extern crate tokio_core; extern crate tokio_io; extern crate tokio_proto; extern crate tokio_service; extern crate tokio_timer; extern crate url; #[cfg(test)] extern crate rand; pub use channel::ChannelBuilder; pub use controller::Controller; pub use dispatcher::ServiceRegistry; pub use server::ServerBuilder; pub use service::MethodError; pub mod channel; pub mod controller; pub mod codec; pub mod dispatcher; pub mod load_balancer; pub mod message; pub mod protocol; pub mod service; pub mod stub; pub mod server; pub mod monitor;