From: Andrea Zagli Date: Sat, 22 Jun 2024 07:15:52 +0000 (+0200) Subject: Replaced actix with axum. X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=6b716301f0d9cd18877792f986ff5eee7adeea10;p=rust%2Fzakgrid Replaced actix with axum. --- diff --git a/Cargo.toml b/Cargo.toml index d6c75d9..56bc9ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ tera = "1.8.0" [dev-dependencies] config = "0.13" -actix-web = "4" +tokio = { version = "1", features = [ "full" ] } +axum = "0.7.5" +axum-macros = "0.4.1" futures = "0.3" sqlx = { version = "0.6", features = [ "runtime-async-std-native-tls", "sqlite" ] } diff --git a/examples/grid.rs b/examples/grid.rs index a8df8e2..321ac02 100644 --- a/examples/grid.rs +++ b/examples/grid.rs @@ -1,31 +1,29 @@ extern crate zakgrid; -use std::any::Any; +use std::{any::Any, sync::Arc}; use config::{Config, ConfigError}; use serde_derive::Deserialize; -use actix_web::{ - body::BoxBody, - dev::ServiceResponse, - error, - http::{header::ContentType, StatusCode}, - middleware::{self, ErrorHandlerResponse, ErrorHandlers}, - web, App, Error, HttpResponse, HttpServer, Responder, Result, +use axum::{ + routing::get, Router, + extract::State, + response::{Html, IntoResponse, Response}, }; +use axum_macros::debug_handler; use futures::TryStreamExt; -use sqlx::{database::HasStatement, sqlite::SqliteStatement, Column, Connection, Execute, Executor, Row, SqliteConnection, Statement}; +use sqlx::{Column, Connection, Executor, Row, SqliteConnection, Statement}; use std::str::FromStr; -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] #[allow(unused)] struct Http { bind_ip: String, bind_port: u16, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] #[allow(unused)] struct Settings { http: Http, @@ -45,14 +43,14 @@ struct AppState { settings: Settings, } -fn get_not_exists(value: &serde_json::Value, user_data: &Option>) -> String { +fn get_not_exists(_value: &serde_json::Value, _user_data: &Option>) -> String { String::from("not exists (returned by fn)") } +#[debug_handler] async fn index( - data: web::Data, -) -> Result { - + State(_state): State>, +) -> Response { let mut grid = zakgrid::Grid::new(); grid.set_header_tmpl(String::from("\n{{ row }}\n")); @@ -73,7 +71,7 @@ async fn index( col.set_title("the second column title"); grid.add_column(col); - let mut col = zakgrid::Column::new("surname"); + let col = zakgrid::Column::new("surname"); grid.add_column(col); let mut col = zakgrid::Column::new("age"); @@ -94,9 +92,9 @@ async fn index( s.push_str(format!("col {} title {}
\n", i, v.title()).as_str()); } - let mut conn = SqliteConnection::connect("examples/grid.db").await.unwrap(); + let mut conn = futures::executor::block_on( async { SqliteConnection::connect("examples/grid.db").await.unwrap() }); - let p = conn.prepare("SELECT * FROM clients WHERE FALSE").await.unwrap(); + let p = futures::executor::block_on( async { conn.prepare("SELECT * FROM clients WHERE FALSE").await.unwrap() }); //let q: sqlx::query::Query<'_, sqlx::Sqlite, _> = sqlx::query("SELECT * FROM clients WHERE FALSE"); //let p = q.statement().unwrap(); @@ -109,7 +107,7 @@ async fn index( s.push_str(header.as_str()); let mut rows = sqlx::query("SELECT * FROM clients").fetch(&mut conn); - while let Some(row) = rows.try_next().await.unwrap() { + while let Some(row) = futures::executor::block_on( async { rows.try_next().await.unwrap() }) { let cols = row.columns(); let mut r = String::new(); @@ -130,14 +128,17 @@ async fn index( s.push_str("\n"); s.push_str("\n"); - Ok(HttpResponse::Ok().body(s)) + Html(s).into_response() } -#[actix_web::main] -async fn main() -> std::io::Result<()> { +#[tokio::main] +async fn main() { + + let settings = Settings::new().unwrap(); + let s2 = settings.clone(); let appstate: AppState = AppState { - settings: Settings::new().unwrap(), + settings: settings, }; // Print out our settings @@ -146,48 +147,16 @@ async fn main() -> std::io::Result<()> { appstate.settings ); - println!("Listening on: {}:{}, open browser and visit have a try!", appstate.settings.http.bind_ip, appstate.settings.http.bind_port); - HttpServer::new(move || { - App::new() - .app_data(web::Data::new(AppState { - settings: Settings::new().unwrap(), - })) - .wrap(middleware::Logger::default()) // enable logger - .service(web::resource("/").route(web::get().to(index))) - .service(web::scope("").wrap(error_handlers())) - }) - .bind((appstate.settings.http.bind_ip, appstate.settings.http.bind_port))? - .run() - .await -} + let shared_state = Arc::new(appstate); -// Custom error handlers, to return HTML responses when an error occurs. -fn error_handlers() -> ErrorHandlers { - ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found) -} -// Error handler for a 404 Page not found error. -fn not_found(res: ServiceResponse) -> Result> { - let response = get_error_response(&res, "Page not found"); - Ok(ErrorHandlerResponse::Response(ServiceResponse::new( - res.into_parts().0, - response.map_into_left_body(), - ))) -} + let app = Router::new() + .route("/", get(index)) + .with_state(shared_state); + + println!("Listening on: {}:{}, open browser and visit have a try!", s2.http.bind_ip, s2.http.bind_port); -// Generic error handler. -fn get_error_response(res: &ServiceResponse, error: &str) -> HttpResponse { - let request = res.request(); - - // Provide a fallback to a simple plain text response in case an error occurs during the - // rendering of the error page. - let fallback = |e: &str| { - HttpResponse::build(res.status()) - .content_type(ContentType::plaintext()) - .body(e.to_string()) - }; - - HttpResponse::build(res.status()) - .content_type(ContentType::html()) - .body("") + // run our app with hyper, listening globally on port 3000 + let listener = tokio::net::TcpListener::bind(format!("{}:{}", s2.http.bind_ip, s2.http.bind_port)).await.unwrap(); + axum::serve(listener, app).await.unwrap(); }