- Add `figment` for config yamls - Small `Makefile.toml` fixes ? (docset seems still broken ??) - Copy `config.yaml` workspace & forge - Embed proxy_man in forge - Remove `backend_process.rs` and `process.rs` - Update `llama_proxy_man/Cargo.toml` and `config.rs` for new dependencies - Format
161 lines
4.7 KiB
Rust
161 lines
4.7 KiB
Rust
use std::str::FromStr;
|
|
|
|
use axum::{
|
|
body::Body,
|
|
extract::{DefaultBodyLimit, FromRef, Path, State},
|
|
http::Request,
|
|
response::IntoResponse,
|
|
routing::get,
|
|
Extension, Router,
|
|
};
|
|
use leptos::*;
|
|
use leptos_axum::{generate_route_list, handle_server_fns_with_context, LeptosRoutes};
|
|
use leptos_router::RouteListing;
|
|
use sqlx::{
|
|
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous},
|
|
ConnectOptions, SqlitePool,
|
|
};
|
|
use tower::Layer;
|
|
use tower_http::{
|
|
compression::CompressionLayer,
|
|
trace::{
|
|
DefaultMakeSpan, DefaultOnEos, DefaultOnFailure, DefaultOnRequest, DefaultOnResponse,
|
|
TraceLayer,
|
|
},
|
|
CompressionLevel,
|
|
};
|
|
use tracing::Level;
|
|
|
|
use self::fileserv::file_and_error_handler;
|
|
use crate::{
|
|
app::*,
|
|
server::middleware::{LoggingLayer, LoggingService},
|
|
};
|
|
|
|
pub mod backends;
|
|
mod fileserv;
|
|
mod middleware;
|
|
|
|
pub fn pool() -> Result<SqlitePool, ServerFnError> {
|
|
use_context::<SqlitePool>().ok_or_else(|| ServerFnError::ServerError("Pool missing.".into()))
|
|
}
|
|
|
|
#[derive(FromRef, Debug, Clone)]
|
|
pub struct AppState {
|
|
pub leptos_options: LeptosOptions,
|
|
pub pool: SqlitePool,
|
|
pub routes: Vec<RouteListing>,
|
|
}
|
|
|
|
pub async fn server_fn_handler(
|
|
State(app_state): State<AppState>,
|
|
path: Path<String>,
|
|
request: Request<Body>,
|
|
) -> impl IntoResponse {
|
|
tracing::debug!("handling server_fn {:?}", path);
|
|
|
|
handle_server_fns_with_context(
|
|
move || {
|
|
provide_context(app_state.pool.clone());
|
|
},
|
|
request,
|
|
)
|
|
.await
|
|
}
|
|
|
|
pub async fn leptos_routes_handler(
|
|
State(app_state): State<AppState>,
|
|
req: Request<Body>,
|
|
) -> impl IntoResponse {
|
|
tracing::debug!("handling leptos_route: {:?}", req);
|
|
|
|
let handler = leptos_axum::render_route_with_context(
|
|
app_state.leptos_options.clone(),
|
|
app_state.routes.clone(),
|
|
move || {
|
|
provide_context(app_state.pool.clone());
|
|
},
|
|
App,
|
|
);
|
|
let response = handler(req).await;
|
|
|
|
tracing::debug!("leptos_route response: {:?}", response);
|
|
response
|
|
}
|
|
|
|
pub async fn app(leptos_options: LeptosOptions) -> Router {
|
|
async fn new_pool() -> Result<SqlitePool, Box<dyn std::error::Error>> {
|
|
// TODO Save this in xdg_config_dir /data dir
|
|
let db_options = SqliteConnectOptions::from_str("sqlite:db.sqlite3")?
|
|
.create_if_missing(true)
|
|
.optimize_on_close(true, None)
|
|
.journal_mode(SqliteJournalMode::Wal)
|
|
.synchronous(SqliteSynchronous::Normal)
|
|
.disable_statement_logging()
|
|
.busy_timeout(std::time::Duration::from_secs(16))
|
|
.statement_cache_capacity(512)
|
|
.to_owned();
|
|
|
|
tracing::debug!(
|
|
msg = "Connectiong to db",
|
|
conn_str = ?db_options.to_url_lossy()
|
|
);
|
|
|
|
let pool = SqlitePoolOptions::new().connect_with(db_options).await?;
|
|
|
|
sqlx::migrate!()
|
|
.run(&pool)
|
|
.await
|
|
.expect("could not run SQLx migrations");
|
|
|
|
Ok(pool)
|
|
}
|
|
|
|
let routes = generate_route_list(App);
|
|
|
|
let pool = new_pool().await.expect("pool err");
|
|
|
|
// // TODO move this out of server(pool has to be moved out too)
|
|
// FIXME: Should proxy_man move here ?
|
|
// let task = run_starter_task(pool.clone());
|
|
// tokio::task::spawn(task);
|
|
|
|
let app_state = AppState {
|
|
leptos_options,
|
|
// stream_registry: Arc::default(),
|
|
pool: pool.clone(),
|
|
routes: routes.clone(),
|
|
};
|
|
|
|
const MAX_BODY_LIMIT: usize = 16 * 1024 * 1024; // 16 MB
|
|
|
|
tracing::debug!("routes: {:?}", routes);
|
|
|
|
// build our application with a route
|
|
Router::new()
|
|
.route(
|
|
"/api/*fn_name",
|
|
get(server_fn_handler).post(server_fn_handler),
|
|
)
|
|
.leptos_routes_with_handler(routes, get(leptos_routes_handler))
|
|
.fallback(file_and_error_handler)
|
|
.with_state(app_state)
|
|
.layer(Extension(pool))
|
|
.layer(
|
|
// Todo Readd gzip & deflate and add compress_when which skips them if response is a stream
|
|
CompressionLayer::new()
|
|
.no_gzip()
|
|
.no_deflate()
|
|
.quality(CompressionLevel::Fastest),
|
|
)
|
|
.layer(
|
|
TraceLayer::new_for_http()
|
|
.make_span_with(DefaultMakeSpan::new().include_headers(true))
|
|
.on_request(DefaultOnRequest::new().level(Level::INFO))
|
|
.on_response(DefaultOnResponse::new().level(Level::INFO))
|
|
.on_eos(DefaultOnEos::new().level(Level::DEBUG))
|
|
.on_failure(DefaultOnFailure::new().level(Level::ERROR)),
|
|
)
|
|
.layer(DefaultBodyLimit::max(MAX_BODY_LIMIT))
|
|
.layer(LoggingLayer)
|
|
}
|