]> saetta.ns0.it Git - rust/zakgrid/commitdiff
Replaced actix with axum. master
authorAndrea Zagli <azagli@libero.it>
Sat, 22 Jun 2024 07:15:52 +0000 (09:15 +0200)
committerAndrea Zagli <azagli@libero.it>
Sat, 22 Jun 2024 07:15:52 +0000 (09:15 +0200)
Cargo.toml
examples/grid.rs

index d6c75d966527fcdc63aafa773e91425aec15fe54..56bc9ba8d3b6e263c90b8dd54ebecd936fe8590e 100644 (file)
@@ -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" ] }
index a8df8e207de75c573f4b82be571d1f27efe158f2..321ac02c020140ad1d182622dc0639d85e1ba105 100644 (file)
@@ -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<Box<dyn Any>>) -> String {
+fn get_not_exists(_value: &serde_json::Value, _user_data: &Option<Box<dyn Any>>) -> String {
        String::from("not exists (returned by fn)")
 }
 
+#[debug_handler]
 async fn index(
-    data: web::Data<AppState>,
-) -> Result<impl Responder, Error> {
-
+       State(_state): State<Arc<AppState>>,
+) -> Response {
        let mut grid = zakgrid::Grid::new();
 
        grid.set_header_tmpl(String::from("<tr style='border: 1px solid;'>\n{{ row }}</tr>\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 {}<br/>\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("</body>\n");
        s.push_str("</html>\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<BoxBody> {
-    ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found)
-}
 
-// Error handler for a 404 Page not found error.
-fn not_found<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<BoxBody>> {
-    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<B>(res: &ServiceResponse<B>, 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();
 }