Sites are now explicitely defined
ci/woodpecker/push/lint Pipeline was successful Details
ci/woodpecker/push/deploy Pipeline was successful Details

This fixes the issue where deploying the default site would delete all
other sites, because they're subdirs of the default dir.
pull/5/head
Jef Roosens 2022-04-05 10:45:42 +02:00
parent 143f892c52
commit 6505e02dd4
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
4 changed files with 46 additions and 17 deletions

2
Cargo.lock generated
View File

@ -829,7 +829,7 @@ dependencies = [
[[package]] [[package]]
name = "site-backend" name = "site-backend"
version = "0.1.3" version = "0.1.4"
dependencies = [ dependencies = [
"axum", "axum",
"flate2", "flate2",

4
curl
View File

@ -2,7 +2,7 @@
curl \ curl \
-XPOST \ -XPOST \
-T test.tar.gz \ -T default.tar.gz \
-H 'Authorization: Bearer test' \ -H 'Authorization: Bearer test' \
-v \ -v \
http://localhost:3000/api/deploy?dir=docs http://localhost:3000/api/deploy

View File

@ -11,7 +11,7 @@ use serde::Deserialize;
use tar::Archive; use tar::Archive;
use tokio_util::io::StreamReader; use tokio_util::io::StreamReader;
use crate::DEFAULT_STATIC_DIR_NAME; use crate::{DEFAULT_STATIC_SITE, STATIC_DIR_NAME};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct StaticDirParams pub struct StaticDirParams
@ -34,11 +34,10 @@ pub async fn post_deploy(
let mut file = tokio::fs::File::create(&file_path).await.unwrap(); let mut file = tokio::fs::File::create(&file_path).await.unwrap();
tokio::io::copy(&mut read, &mut file).await; tokio::io::copy(&mut read, &mut file).await;
let mut static_path = Path::new(&data_dir).join(DEFAULT_STATIC_DIR_NAME); // If no dir is provided, we use the default one. Otherwise, use the provided one.
let static_path = Path::new(&data_dir)
if params.dir.is_some() { .join(STATIC_DIR_NAME)
static_path = static_path.join(params.dir.unwrap()); .join(params.dir.unwrap_or(DEFAULT_STATIC_SITE.to_string()));
}
// Make sure the static directory exists // Make sure the static directory exists
tokio::fs::create_dir_all(&static_path).await; tokio::fs::create_dir_all(&static_path).await;

View File

@ -14,7 +14,10 @@ mod api;
mod matrix; mod matrix;
mod metrics; mod metrics;
const DEFAULT_STATIC_DIR_NAME: &str = "static"; /// Name of the directory where static sites are stored inside the data directory
const STATIC_DIR_NAME: &str = "static";
/// Name of the subdir of STATIC_DIR_NAME where the default (fallback) site is located
const DEFAULT_STATIC_SITE: &str = "default";
#[tokio::main] #[tokio::main]
async fn main() async fn main()
@ -30,13 +33,14 @@ async fn main()
// Get required variables from env vars // Get required variables from env vars
let api_key = std::env::var("API_KEY").expect("No API_KEY was provided."); let api_key = std::env::var("API_KEY").expect("No API_KEY was provided.");
let data_dir = std::env::var("DATA_DIR").expect("No DATA_DIR was provided."); let data_dir = std::env::var("DATA_DIR").expect("No DATA_DIR was provided.");
let static_dir = format!("{}/{}", data_dir, DEFAULT_STATIC_DIR_NAME); let static_dir = format!("{}/{}", data_dir, STATIC_DIR_NAME);
std::fs::create_dir_all(&static_dir); std::fs::create_dir_all(&static_dir);
// Initialize metrics
let recorder_handle = metrics::setup_metrics_recorder(); let recorder_handle = metrics::setup_metrics_recorder();
let app = Router::new() let mut app = Router::new()
// Handle Matrix .well-known files // Handle Matrix .well-known files
.nest("/", matrix::router()) .nest("/", matrix::router())
// Routes under /api path // Routes under /api path
@ -44,16 +48,42 @@ async fn main()
"/api", "/api",
api::router().layer(RequireAuthorizationLayer::bearer(&api_key)), api::router().layer(RequireAuthorizationLayer::bearer(&api_key)),
) )
.route("/metrics", get(move || ready(recorder_handle.render()))) .route("/metrics", get(move || ready(recorder_handle.render())));
// Each static site gets mounted explicitely so that the default site can be used as fallback
// Each entry is of the form (route, static dir name)
let sites = [("/docs", "docs")];
for (path, dir) in sites {
let full_path = format!("{}/{}", static_dir, dir);
app = app.nest(
path,
get_service(ServeDir::new(full_path)).handle_error(
|error: std::io::Error| async move {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled internal error: {}", error),
)
},
),
);
}
app = app
// The fallback option is to serve the actual static files // The fallback option is to serve the actual static files
.fallback(get_service(ServeDir::new(static_dir)).handle_error( .fallback(
|error: std::io::Error| async move { get_service(ServeDir::new(format!(
"{}/{}",
static_dir, DEFAULT_STATIC_SITE
)))
.handle_error(|error: std::io::Error| async move {
( (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled internal error: {}", error), format!("Unhandled internal error: {}", error),
) )
}, }),
)) )
.layer(middleware::from_fn(metrics::track_metrics)) .layer(middleware::from_fn(metrics::track_metrics))
.layer(Extension(data_dir)) .layer(Extension(data_dir))
.layer(TraceLayer::new_for_http()); .layer(TraceLayer::new_for_http());