Skip to content

Commit

Permalink
feat: work on multihost routing
Browse files Browse the repository at this point in the history
  • Loading branch information
n-dusan committed Dec 21, 2023
1 parent 109ff61 commit 754da83
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 32 deletions.
50 changes: 39 additions & 11 deletions src/server/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ fn clean_path(path: &str) -> String {

/// Global, read-only state
#[derive(Debug, Clone)]
pub struct AppState {
pub struct AppState<'app> {
/// Fully initialized Stelae archive
pub archive: Archive,
pub archive: Archive<'app>,
}

/// Git repository to serve
Expand Down Expand Up @@ -185,7 +185,7 @@ pub async fn serve_archive(
let root = state.archive.get_root().unwrap();
let shared_state = init_shared_app_state(root);
// let shared_state = SharedState { fallback: None };
dbg!(&shared_state);
dbg!(&state);

HttpServer::new(move || init_app(shared_state.clone(), state.clone()))
.bind((bind, port))?
Expand All @@ -207,12 +207,40 @@ pub fn init_app(
Error = Error,
>,
> {
App::new().service(
web::scope("")
.app_data(web::Data::new(shared_state))
.wrap(TracingLogger::<StelaeRootSpanBuilder>::new())
.configure(|cfg| init_routes(cfg, state)),
)
let config = state.archive.get_config().unwrap_or_else(|_| {
tracing::error!("Unable to parse config file.");
std::process::exit(1);
});
let stelae_custom_header = config
.headers
.and_then(|headers| headers.stelae_use_custom_header);

match stelae_custom_header {
Some(header) => {
lazy_static! {
static ref HEADER: &'static str = || { header };
}
let mut app = App::new();
for name in state.archive.stelae.keys() {
let mut stelae_scope = web::scope("");

stelae_scope = stelae_scope.guard(guard::Header(header, &name));
app = app.service(stelae_scope);
}
App::new().service(
web::scope("")
.app_data(web::Data::new(shared_state))
.wrap(TracingLogger::<StelaeRootSpanBuilder>::new())
.configure(|cfg| init_routes(cfg, state)),
)
}
None => App::new().service(
web::scope("")
.app_data(web::Data::new(shared_state))
.wrap(TracingLogger::<StelaeRootSpanBuilder>::new())
.configure(|cfg| init_routes(cfg, state)),
),
}
}

/// Routes
Expand All @@ -238,7 +266,7 @@ fn init_routes(cfg: &mut web::ServiceConfig, mut state: AppState) {
repo: Repo {
archive_path: state.archive.path.to_string_lossy().to_string(),
path: PathBuf::from(repo_path.clone()),
org: stele.org.clone(),
org: stele.org.to_string(),
name: name.to_string(),
repo: Repository::open(repo_path)
.expect("Unable to open Git repository"),
Expand Down Expand Up @@ -292,7 +320,7 @@ fn init_routes(cfg: &mut web::ServiceConfig, mut state: AppState) {
repo: Repo {
archive_path: state.archive.path.to_string_lossy().to_string(),
path: PathBuf::from(repo_path.clone()),
org: stele.org.clone(),
org: stele.org.to_string(),
name: name.to_string(),
repo: Repository::open(repo_path)
.expect("Unable to open Git repository"),
Expand Down
35 changes: 23 additions & 12 deletions src/stelae/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@ use crate::stelae::stele;
use crate::stelae::stele::Stele;
use crate::utils::archive::{find_archive_path, get_name_parts};
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::HashMap;
use std::fs::{create_dir_all, read_to_string, write};
use std::path::{Path, PathBuf};

/// The Archive struct is used for interacting with a Stelae Archive.
#[derive(Debug, Clone)]
pub struct Archive {
pub struct Archive<'archive> {
/// Path to the Archive
pub path: PathBuf,
/// map of auth repo name to Stele object
pub stelae: HashMap<String, Stele>,
pub stelae: HashMap<&'archive str, Stele<'archive>>,
}

impl Archive {
impl<'archive> Archive<'archive> {
/// Get an archive's config object.
/// # Errors
/// Will error if unable to find or parse config file at `.stelae/config.toml`
Expand Down Expand Up @@ -60,13 +61,13 @@ impl Archive {

root = Stele::new(
self.path.clone(),
Some(name),
Some(org.clone()),
Some(self.path.clone().join(org)),
Some(&name),
Some(&org),
Some(self.path.clone().join(&org)),
true,
)?;
}
self.stelae.insert(root.get_qualified_name(), root);
self.stelae.insert(&root.get_qualified_name(), root);
Ok(())
}

Expand Down Expand Up @@ -106,13 +107,13 @@ impl Archive {
let (org, name) = get_name_parts(&qualified_name)?;
let child = Stele::new(
self.path.clone(),
Some(name),
Some(org.clone()),
Some(parent_dir.join(org)),
Some(&name),
Some(&org),
Some(parent_dir.join(&org)),
false,
)?;
self.stelae
.entry(format!("{}/{}", child.org, child.name))
.entry(&format!("{}/{}", child.org, child.name))
.or_insert_with(|| child.clone());
self.traverse_children(&child)?;
}
Expand All @@ -139,6 +140,15 @@ pub struct Config {
root: stele::Config,
/// Whether this is a shallow archive (all repos depth=1)
shallow: bool,
/// Custom headers used to interact with the Stele
pub headers: Option<Headers>,
}

/// Headers object for an Archive
#[derive(Default, Deserialize, Serialize)]
pub struct Headers {
/// Specify a custom header to use when requesting a Stele's current documents.
pub stelae_use_custom_header: Option<&'static str>,
}

/// Create a new Stelae Archive at path, and return the new archive.
Expand All @@ -150,7 +160,7 @@ pub fn init(
root_org: String,
root_hash: Option<String>,
shallow: bool,
) -> anyhow::Result<Box<Archive>> {
) -> anyhow::Result<Box<Archive<'static>>> {
raise_error_if_in_existing_archive(&path)?;
let stelae_dir = path.join(PathBuf::from("./.stelae"));
create_dir_all(&stelae_dir)?;
Expand All @@ -162,6 +172,7 @@ pub fn init(
hash: root_hash,
},
shallow,
headers: None,
};
let conf_str = toml_edit::ser::to_string_pretty(&conf)?;
write(config_path, conf_str)?;
Expand Down
17 changes: 8 additions & 9 deletions src/stelae/stele.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ use super::types::repositories::Repository;

/// Stele
#[derive(Debug, Clone)]
pub struct Stele {
pub struct Stele<'stele> {
/// Path to the containing Stelae archive.
pub archive_path: PathBuf,
/// Name of the authentication repo (e.g. law).
pub name: String,
pub name: &'stele str,
/// Name of the Stele's directory, also known as Stele's organization (e.g. openlawlibrary).
pub org: String,
pub org: &'stele str,
/// Full path to the Stele's directory.
pub path: PathBuf,
/// Stele's repositories (as specified in repositories.json).
Expand All @@ -28,7 +28,7 @@ pub struct Stele {
pub root: bool,
}

impl Stele {
impl<'stele> Stele<'stele> {
/// Create a new Stele object
/// # Errors
/// Will error if unable to find or parse repositories file at `targets/repositories.json`
Expand All @@ -37,20 +37,19 @@ impl Stele {
#[allow(clippy::unwrap_used, clippy::shadow_reuse)]
pub fn new(
archive_path: PathBuf,
name: Option<String>,
org: Option<String>,
name: Option<&str>,
org: Option<&str>,
path: Option<PathBuf>,
root: bool,
) -> anyhow::Result<Self> {
let name = name.unwrap_or_else(|| "law".to_owned());
let name = name.unwrap_or_else(|| "law");
let org = org.unwrap_or_else(|| {
path.as_ref()
.unwrap()
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_owned()
});
let path = path.unwrap_or_else(|| archive_path.join(&org));
let mut stele = Self {
Expand Down Expand Up @@ -98,7 +97,7 @@ impl Stele {
/// Get Stele's qualified name.
#[must_use]
pub fn get_qualified_name(&self) -> String {
format!("{}/{}", self.org, self.name)
format!("{}/{}", self.org.to_string(), self.name.to_string())
}

/// Get Stele's fallback repo.
Expand Down
2 changes: 2 additions & 0 deletions src/stelae/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
//! The Types module contains data models for Stelae.
pub mod dependencies;
pub mod repositories;

0 comments on commit 754da83

Please sign in to comment.