Add tower server example (#375)

Note that this also adds `impl From<Status> for http::Response<BoxBody>`
in order to make writing middleware which can return an error much
easier.
This commit is contained in:
Kaleb Elwert
2020-06-22 12:04:02 -04:00
committed by GitHub
parent 54d7a7af6b
commit 80e90e3b5d
3 changed files with 98 additions and 0 deletions
+4
View File
@@ -66,6 +66,10 @@ path = "src/tls_client_auth/server.rs"
name = "tls-client-auth-client"
path = "src/tls_client_auth/client.rs"
[[bin]]
name = "tower-server"
path = "src/tower/server.rs"
[[bin]]
name = "multiplex-server"
path = "src/multiplex/server.rs"
+8
View File
@@ -94,6 +94,14 @@ $ cargo run --bin tls-server
$ cargo run --bin health-server
```
## Tower Middleware
### Server
```bash
$ cargo run --bin tower-server
```
## Autoreloading Server
### Server
+86
View File
@@ -0,0 +1,86 @@
use hyper::{Body, Request as HyperRequest, Response as HyperResponse};
use std::task::{Context, Poll};
use tonic::{
body::BoxBody,
transport::{NamedService, Server},
Request, Response, Status,
};
use tower::Service;
use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
pub mod hello_world {
tonic::include_proto!("helloworld");
}
#[derive(Default)]
pub struct MyGreeter {}
#[tonic::async_trait]
impl Greeter for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>,
) -> Result<Response<HelloReply>, Status> {
println!("Got a request from {:?}", request.remote_addr());
let reply = hello_world::HelloReply {
message: format!("Hello {}!", request.into_inner().name),
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse().unwrap();
let greeter = MyGreeter::default();
println!("GreeterServer listening on {}", addr);
let svc = InterceptedService {
inner: GreeterServer::new(greeter),
};
Server::builder().add_service(svc).serve(addr).await?;
Ok(())
}
#[derive(Debug, Clone)]
struct InterceptedService<S> {
inner: S,
}
impl<S> Service<HyperRequest<Body>> for InterceptedService<S>
where
S: Service<HyperRequest<Body>, Response = HyperResponse<BoxBody>>
+ NamedService
+ Clone
+ Send
+ 'static,
S::Future: Send + 'static,
{
type Response = S::Response;
type Error = S::Error;
type Future = futures::future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: HyperRequest<Body>) -> Self::Future {
let mut svc = self.inner.clone();
Box::pin(async move {
// Do async work here....
svc.call(req).await
})
}
}
impl<S: NamedService> NamedService for InterceptedService<S> {
const NAME: &'static str = S::NAME;
}