Support nesting services with error handling

This commit is contained in:
David Pedersen
2021-06-01 11:23:56 +02:00
parent 093ad3622e
commit f690e74275
8 changed files with 288 additions and 96 deletions
+14 -9
View File
@@ -1,9 +1,8 @@
use http::Request;
use http::{Request, StatusCode};
use hyper::Server;
use std::net::SocketAddr;
use tower::{make::Shared, ServiceBuilder};
use tower_http::trace::TraceLayer;
use tower_web::{body::Body, response::Html};
use tower::make::Shared;
use tower_web::{body::Body, extract, response::Html};
#[tokio::main]
async fn main() {
@@ -13,14 +12,11 @@ async fn main() {
let app = tower_web::app()
.at("/")
.get(handler)
.at("/greet/:name")
.get(greet)
// convert it into a `Service`
.into_service();
// add some middleware
let app = ServiceBuilder::new()
.layer(TraceLayer::new_for_http())
.service(app);
// run it with hyper
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
@@ -31,3 +27,12 @@ async fn main() {
async fn handler(_req: Request<Body>) -> Html<&'static str> {
Html("<h1>Hello, World!</h1>")
}
async fn greet(_req: Request<Body>, params: extract::UrlParamsMap) -> Result<String, StatusCode> {
if let Some(name) = params.get("name") {
Ok(format!("Hello {}!", name))
} else {
// if the route matches "name" will be present
Err(StatusCode::INTERNAL_SERVER_ERROR)
}
}
+2 -9
View File
@@ -11,7 +11,7 @@ use tower::{make::Shared, ServiceBuilder};
use tower_http::{
add_extension::AddExtensionLayer, compression::CompressionLayer, trace::TraceLayer,
};
use tower_web::{body::Body, extract};
use tower_web::{body::Body, extract, handler::Handler};
#[tokio::main]
async fn main() {
@@ -20,7 +20,7 @@ async fn main() {
// build our application with some routes
let app = tower_web::app()
.at("/:key")
.get(get)
.get(get.layer(CompressionLayer::new()))
.post(set)
// convert it into a `Service`
.into_service();
@@ -29,7 +29,6 @@ async fn main() {
let app = ServiceBuilder::new()
.timeout(Duration::from_secs(10))
.layer(TraceLayer::new_for_http())
.layer(CompressionLayer::new())
.layer(AddExtensionLayer::new(SharedState::default()))
.service(app);
@@ -51,10 +50,6 @@ async fn get(
_req: Request<Body>,
params: extract::UrlParams<(String,)>,
state: extract::Extension<SharedState>,
// Anything that implements `IntoResponse` can be used a response
//
// Handlers cannot return errors. Everything will be converted
// into a response. `BoxError` becomes `500 Internal server error`
) -> Result<Bytes, StatusCode> {
let state = state.into_inner();
let db = &state.lock().unwrap().db;
@@ -73,8 +68,6 @@ async fn set(
params: extract::UrlParams<(String,)>,
value: extract::BytesMaxLength<{ 1024 * 5_000 }>, // ~5mb
state: extract::Extension<SharedState>,
// `()` also implements `IntoResponse` so we can use that to return
// an empty response
) {
let state = state.into_inner();
let db = &mut state.lock().unwrap().db;