4 routing::{get, get_service},
5 extract::{Path, TypedHeader, ws},
10 async fn hello(Path(name): Path<String>, user_agent: Option<TypedHeader<axum::headers::UserAgent>>) -> impl response::IntoResponse {
11 if let Some(TypedHeader(user_agent)) = user_agent {
12 (StatusCode::OK, format!("Hello {} from {}", name, user_agent))
14 (StatusCode::OK, format!("Hello {}", name))
18 async fn ws_echo(mut socket: ws::WebSocket) {
19 while let Some(msg) = socket.recv().await {
20 if let Ok(msg) = msg {
21 tracing::debug!("websocket got message: {:?}", msg);
23 let reply = match msg {
24 ws::Message::Text(t) => ws::Message::Text(t),
25 ws::Message::Binary(b) => ws::Message::Binary(b),
26 // axum handles Ping/Pong by itself
27 ws::Message::Ping(_) => { continue },
28 ws::Message::Pong(_) => { continue },
29 ws::Message::Close(_) => { break }
32 if socket.send(reply).await
34 tracing::info!("websocket client disconnected");
39 tracing::info!("websocket client disconnected");
47 tracing_subscriber::fmt::init();
48 let app = Router::new()
49 .route("/hello/:name", get(hello))
51 get_service(tower_http::services::ServeFile::new("Cargo.toml").precompressed_gzip())
52 .handle_error(|e: io::Error| async move {
53 (StatusCode::INTERNAL_SERVER_ERROR, format!("Unhandled internal error: {}", e))
56 .route("/ws-echo", get(|ws: ws::WebSocketUpgrade| async {ws.on_upgrade(ws_echo)}))
58 tower::ServiceBuilder::new()
60 tower_http::trace::TraceLayer::new_for_http()
61 .make_span_with(tower_http::trace::DefaultMakeSpan::default().include_headers(true)),
65 let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3000));
66 tracing::info!("listening on {}", addr);
67 axum::Server::bind(&addr)
68 .serve(app.into_make_service())