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,
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"));
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");
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();
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();
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
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();
}