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]]
name = "site-backend"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"axum",
"flate2",

4
curl
View File

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

View File

@ -14,7 +14,10 @@ mod api;
mod matrix;
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]
async fn main()
@ -30,13 +33,14 @@ async fn main()
// Get required variables from env vars
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 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);
// Initialize metrics
let recorder_handle = metrics::setup_metrics_recorder();
let app = Router::new()
let mut app = Router::new()
// Handle Matrix .well-known files
.nest("/", matrix::router())
// Routes under /api path
@ -44,16 +48,42 @@ async fn main()
"/api",
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
.fallback(get_service(ServeDir::new(static_dir)).handle_error(
|error: std::io::Error| async move {
.fallback(
get_service(ServeDir::new(format!(
"{}/{}",
static_dir, DEFAULT_STATIC_SITE
)))
.handle_error(|error: std::io::Error| async move {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled internal error: {}", error),
)
},
))
}),
)
.layer(middleware::from_fn(metrics::track_metrics))
.layer(Extension(data_dir))
.layer(TraceLayer::new_for_http());