// Copyright 2022 Daniel Arbuckle // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Run with `cargo run --example axum --features examples` use std::{net::TcpListener, sync::Arc}; use axum::{ response::{Html, IntoResponse}, routing::{get, post}, Extension, Router, Server, }; use tokio::sync::{ oneshot::{channel, Sender}, Mutex, }; struct State { shutdown: Option>, } async fn index() -> impl IntoResponse { Html( r#"Hello World.
"#, ) } async fn shutdown(Extension(state): Extension>>) -> impl IntoResponse { if let Some(shutdown) = state.lock().await.shutdown.take() { let _ = shutdown.send(()); "Shutting down" } else { "Shutdown already initiated" } } fn main() { // Non-async set up. We can do any server configuration that // doesn't need an async context here, parse the command line, // etc. let (shutdown_tx, shutdown_rx) = channel::<()>(); let state = Arc::new(Mutex::new(State { shutdown: Some(shutdown_tx), })); let app = Router::new() .route("/", get(index)) .route("/shutdown", post(shutdown)) .layer(Extension(state)); // Pick a random available port on the loopback interface. Not // actually required, but usually a good idea. let ear = TcpListener::bind("127.0.0.1:0").expect("bind port"); let addr = ear.local_addr().expect("retrieve port"); // Here we start up the webview and actually run the server. The // async block is the asynchronous entry point for the program // (like tokio::main or async_std::main), so any server set up // code that needs to run in an async context should be there, as // well as the code to actually run the server. When the async // block finishes executing, the program will close. drteeth::launch("Axum Demo", addr, async move { Server::from_tcp(ear) .unwrap() .serve(app.into_make_service()) .with_graceful_shutdown(async { shutdown_rx.await.ok(); }) .await .unwrap(); }) .unwrap(); }