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:
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user