mirror of
https://github.com/tokio-rs/tracing.git
synced 2026-03-30 19:29:24 +00:00
This PR fixes all reported clippy lints. In most cases I have made the suggested changes. In a few cases (e.g., `blacklisted_name` and `cognitive_complexity`) I've just silenced the warning. I can make stylistic changes or discard some of the lint fixes if preferred.
151 lines
5.2 KiB
Rust
151 lines
5.2 KiB
Rust
#![deny(rust_2018_idioms)]
|
|
|
|
use futures::future;
|
|
use hyper::rt::{Future, Stream};
|
|
use hyper::server::conn::Http;
|
|
use hyper::service::service_fn;
|
|
use hyper::{Body, Method, Request, Response, StatusCode};
|
|
|
|
use std::str;
|
|
|
|
use tracing::{debug, error, info, span, Level};
|
|
use tracing_futures::{Instrument, Instrumented};
|
|
|
|
type BoxFut = Box<dyn Future<Item = Response<Body>, Error = hyper::Error> + Send>;
|
|
|
|
fn echo(req: Request<Body>) -> Instrumented<BoxFut> {
|
|
let span = span!(
|
|
Level::INFO,
|
|
"request",
|
|
method = ?req.method(),
|
|
uri = ?req.uri(),
|
|
headers = ?req.headers()
|
|
);
|
|
let _enter = span.enter();
|
|
info!("received request");
|
|
let mut response = Response::new(Body::empty());
|
|
|
|
let (rsp_span, fut): (_, BoxFut) = match (req.method(), req.uri().path()) {
|
|
// Serve some instructions at /
|
|
(&Method::GET, "/") => {
|
|
const BODY: &str = "Try POSTing data to /echo";
|
|
*response.body_mut() = Body::from(BODY);
|
|
(
|
|
span!(Level::INFO, "response", body = %(&BODY)),
|
|
Box::new(future::ok(response)),
|
|
)
|
|
}
|
|
|
|
// Simply echo the body back to the client.
|
|
(&Method::POST, "/echo") => {
|
|
let body = req.into_body();
|
|
let span = span!(Level::INFO, "response", response_kind = %"echo");
|
|
*response.body_mut() = body;
|
|
(span, Box::new(future::ok(response)))
|
|
}
|
|
|
|
// Convert to uppercase before sending back to client.
|
|
(&Method::POST, "/echo/uppercase") => {
|
|
let mapping = req.into_body().map(|chunk| {
|
|
let upper = chunk
|
|
.iter()
|
|
.map(|byte| byte.to_ascii_uppercase())
|
|
.collect::<Vec<u8>>();
|
|
debug!(
|
|
message = "uppercased request body",
|
|
chunk = ?str::from_utf8(&chunk[..]),
|
|
uppercased = ?str::from_utf8(&upper[..])
|
|
);
|
|
upper
|
|
});
|
|
|
|
*response.body_mut() = Body::wrap_stream(mapping);
|
|
(
|
|
span!(Level::INFO, "response", response_kind = %"uppercase"),
|
|
Box::new(future::ok(response)),
|
|
)
|
|
}
|
|
|
|
// Reverse the entire body before sending back to the client.
|
|
//
|
|
// Since we don't know the end yet, we can't simply stream
|
|
// the chunks as they arrive. So, this returns a different
|
|
// future, waiting on concatenating the full body, so that
|
|
// it can be reversed. Only then can we return a `Response`.
|
|
(&Method::POST, "/echo/reversed") => {
|
|
let span = span!(Level::TRACE, "response", response_kind = %"reversed");
|
|
let _enter = span.enter();
|
|
let reversed = req.into_body().concat2().map(move |chunk| {
|
|
let body = chunk.iter().rev().cloned().collect::<Vec<u8>>();
|
|
debug!(
|
|
message = "reversed request body",
|
|
chunk = ?str::from_utf8(&chunk[..]),
|
|
body = ?str::from_utf8(&body[..]),
|
|
);
|
|
*response.body_mut() = Body::from(body);
|
|
response
|
|
});
|
|
(span.clone(), Box::new(reversed))
|
|
}
|
|
|
|
// The 404 Not Found route...
|
|
_ => {
|
|
*response.status_mut() = StatusCode::NOT_FOUND;
|
|
(
|
|
span!(
|
|
Level::TRACE,
|
|
"response",
|
|
body = ?(),
|
|
status = ?StatusCode::NOT_FOUND,
|
|
),
|
|
Box::new(future::ok(response)),
|
|
)
|
|
}
|
|
};
|
|
|
|
fut.instrument(rsp_span)
|
|
}
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
use tracing_log::env_logger::BuilderExt;
|
|
|
|
let subscriber = tracing_subscriber::FmtSubscriber::builder()
|
|
.with_max_level(Level::TRACE)
|
|
.finish();
|
|
let mut builder = env_logger::Builder::new();
|
|
builder
|
|
.filter(Some("hyper_echo"), log::LevelFilter::Off)
|
|
.filter(Some("hyper"), log::LevelFilter::Trace)
|
|
.emit_traces() // from `tracing_log::env_logger::BuilderExt`
|
|
.try_init()?;
|
|
tracing::subscriber::set_global_default(subscriber)?;
|
|
|
|
let local_addr: std::net::SocketAddr = ([127, 0, 0, 1], 3000).into();
|
|
let server_span = span!(Level::TRACE, "server", %local_addr);
|
|
let _enter = server_span.enter();
|
|
|
|
let server = tokio::net::TcpListener::bind(&local_addr)
|
|
.expect("bind")
|
|
.incoming()
|
|
.fold(Http::new(), move |http, sock| {
|
|
let remote_addr = sock.peer_addr().unwrap();
|
|
let serve = http
|
|
.serve_connection(sock, service_fn(echo))
|
|
.map_err(|error| {
|
|
error!(message = "serve error", %error);
|
|
})
|
|
.instrument(span!(Level::TRACE, "connection", %remote_addr));
|
|
hyper::rt::spawn(serve);
|
|
Ok::<_, std::io::Error>(http)
|
|
})
|
|
.map(|_| ())
|
|
.map_err(|error| {
|
|
error!(message = "server error", %error);
|
|
})
|
|
.instrument(server_span.clone());
|
|
info!("listening...");
|
|
hyper::rt::run(server);
|
|
|
|
Ok(())
|
|
}
|