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"
|
name = "tls-client-auth-client"
|
||||||
path = "src/tls_client_auth/client.rs"
|
path = "src/tls_client_auth/client.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "tower-server"
|
||||||
|
path = "src/tower/server.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "multiplex-server"
|
name = "multiplex-server"
|
||||||
path = "src/multiplex/server.rs"
|
path = "src/multiplex/server.rs"
|
||||||
|
|||||||
@@ -94,6 +94,14 @@ $ cargo run --bin tls-server
|
|||||||
$ cargo run --bin health-server
|
$ cargo run --bin health-server
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Tower Middleware
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo run --bin tower-server
|
||||||
|
```
|
||||||
|
|
||||||
## Autoreloading Server
|
## Autoreloading Server
|
||||||
|
|
||||||
### 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