use log::{error, info}; use rouille::{router, Request, Response}; use crate::{ private_router, routes, utils::{flash::FlashResponse, sbot}, SessionData, }; /// Request handler. /// /// Mount the fileservers for static assets and define the /// publically-accessible routes (including per-route handlers). Includes /// logging of all incoming requests. /// /// If the request is for a private route (ie. a route requiring successful /// authentication to view), check the authentication status of the user /// by querying the `session_data`. If the user is authenticated, pass their /// request to the private router. Otherwise, redirect them to the login page. pub fn handle_route(request: &Request, session_data: &mut Option) -> Response { // static file server // matches on assets in the `static` directory let static_response = rouille::match_assets(request, "static"); if static_response.is_success() { return static_response; } // set the `.ssb-go` path in order to mount the blob fileserver let ssb_path = sbot::get_go_ssb_path().expect("define ssb-go dir path"); let blobstore = format!("{}/blobs/sha256", ssb_path); // blobstore file server // removes the /blob url prefix and serves blobs from blobstore // matches on assets in the `static` directory if let Some(request) = request.remove_prefix("/blob") { return rouille::match_assets(&request, &blobstore); } // get the current time (for logging purposes) let now = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S%.6f"); // define the success logger for incoming requests let log_ok = |req: &Request, _resp: &Response, _elap: std::time::Duration| { info!("{} {} {}", now, req.method(), req.raw_url()); }; // define the error logger for incoming requests let log_err = |req: &Request, _elap: std::time::Duration| { error!( "{} Handler panicked: {} {}", now, req.method(), req.raw_url() ); }; // instantiate request logging rouille::log_custom(request, log_ok, log_err, || { // handle the routes which are always accessible (ie. whether logged-in // or not) router!(request, (GET) (/auth/forgot) => { Response::html(routes::authentication::forgot::build_template(request)) .reset_flash() }, (GET) (/auth/login) => { Response::html(routes::authentication::login::build_template(request)) .reset_flash() }, (POST) (/auth/login) => { routes::authentication::login::handle_form(request, session_data) }, (GET) (/auth/reset) => { Response::html(routes::authentication::reset::build_template(request)) .reset_flash() }, (POST) (/auth/reset) => { routes::authentication::reset::handle_form(request) }, (POST) (/auth/temporary) => { routes::authentication::temporary::handle_form() }, _ => { // now that we handled all the routes that are accessible in all // circumstances, we check that the user is logged in before proceeding if let Some(_session) = session_data.as_ref() { // logged in: // mount the routes which require authentication to view private_router::mount_peachpub_routes(request, session_data) } else { // not logged in: Response::redirect_303("/auth/login") } } ) }) }