Skip to content

Commit

Permalink
move out asset server token map to asset_server mod
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-berger committed Dec 10, 2024
1 parent 9e7202b commit c15d322
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 76 deletions.
84 changes: 52 additions & 32 deletions packages/desktop/src/asset_server.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
use std::{
collections::HashMap,
io::Cursor,
path::{Path, PathBuf},
sync::Arc,
sync::LazyLock,
};

use rocket::{
fs::NamedFile,
http::{ContentType, Cookie, CookieJar, Header, SameSite, Status},
request::{FromRequest, Outcome},
response::{self, Redirect, Responder, Response},
tokio::task,
Request, State,
Request,
};
use tokio::{sync::Mutex, task};
use uuid::Uuid;

use crate::{
common::PathExt, config::Config, widget_factory::WidgetFactory,
};
use crate::common::PathExt;

/// Port for the localhost asset server.
const ASSET_SERVER_PORT: u16 = 6124;

/// Map of tokens to their corresponding path.
static ASSET_SERVER_TOKENS: LazyLock<Mutex<HashMap<String, PathBuf>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));

pub fn setup_asset_server(
config: Arc<Config>,
widget_factory: Arc<WidgetFactory>,
) {
pub fn setup_asset_server() {
task::spawn(async move {
let rocket = rocket::build()
.configure(rocket::Config::figment().merge(("port", 6124)))
.manage(config)
.manage(widget_factory)
.configure(
rocket::Config::figment().merge(("port", ASSET_SERVER_PORT)),
)
.mount("/", routes![sw_js, normalize_css, init, serve]);

if let Err(err) = rocket.launch().await {
Expand All @@ -35,32 +39,48 @@ pub fn setup_asset_server(
}

pub async fn create_init_url(
widget_factory: &WidgetFactory,
parent_dir: &Path,
html_path: &Path,
) -> anyhow::Result<tauri::Url> {
// Generate a unique token to identify requests from the widget to the
// asset server.
let token = upsert_or_get_token(parent_dir).await;

let redirect = format!(
"/{}",
html_path.strip_prefix(parent_dir)?.to_unicode_string()
);

let url = tauri::Url::parse_with_params(
"http://127.0.0.1:6124/__zebar/init",
&[
(
"token",
// Generate a unique token to identify requests from the
// widget to the asset server.
&widget_factory.upsert_or_get_token(parent_dir).await,
),
(
"redirect",
&format!(
"/{}",
html_path.strip_prefix(parent_dir)?.to_unicode_string()
),
),
],
&format!("http://127.0.0.1:{}/__zebar/init", ASSET_SERVER_PORT),
&[("token", &token), ("redirect", &redirect)],
)?;

Ok(url)
}

/// Returns an asset server token for a given directory.
///
/// If the directory does not have an existing token, a new one is
/// generated and inserted.
async fn upsert_or_get_token(directory: &Path) -> String {
let mut asset_server_tokens = ASSET_SERVER_TOKENS.lock().await;

// Find existing token for this path.
let found_token = asset_server_tokens
.iter()
.find(|(_, path)| *path == directory)
.map(|(token, _)| token.clone());

found_token.unwrap_or_else(|| {
let new_token = Uuid::new_v4().to_string();

asset_server_tokens.insert(new_token.clone(), directory.to_path_buf());

new_token
})
}

#[get("/__zebar/init?<token>&<redirect>")]
pub fn init(
token: String,
Expand Down Expand Up @@ -106,10 +126,10 @@ pub fn normalize_css() -> (ContentType, &'static str) {
pub async fn serve(
path: Option<PathBuf>,
token: ServerToken,
widget_factory: &State<Arc<WidgetFactory>>,
) -> Option<NamedFile> {
// Retrieve base directory for the corresponding token.
let base_url = widget_factory.directory_by_token(&token.0).await?;
let base_url =
{ ASSET_SERVER_TOKENS.lock().await.get(&token.0).cloned() }?;

let asset_path = base_url
.join(path.unwrap_or("index.html".into()))
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ async fn start_app(app: &mut tauri::App, cli: Cli) -> anyhow::Result<()> {
// guaranteed to be one of the open commands here.
setup_single_instance(app, widget_factory.clone())?;

setup_asset_server(config.clone(), widget_factory.clone());
setup_asset_server();

// Prevent windows from showing up in the dock on MacOS.
#[cfg(target_os = "macos")]
Expand Down
45 changes: 2 additions & 43 deletions packages/desktop/src/widget_factory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
collections::HashMap,
path::{Path, PathBuf},
path::PathBuf,
sync::{
atomic::{AtomicU32, Ordering},
Arc,
Expand All @@ -19,7 +19,6 @@ use tokio::{
task,
};
use tracing::{error, info};
use uuid::Uuid;

#[cfg(target_os = "macos")]
use crate::common::macos::WindowExtMacOs;
Expand All @@ -44,9 +43,6 @@ pub struct WidgetFactory {

pub close_tx: broadcast::Sender<String>,

/// Map of directory tokens to their corresponding path.
asset_server_tokens: Arc<Mutex<HashMap<String, PathBuf>>>,

/// Reference to `Config`.
config: Arc<Config>,

Expand Down Expand Up @@ -168,7 +164,6 @@ impl WidgetFactory {
_close_rx,
close_tx,
config,
asset_server_tokens: Arc::new(Mutex::new(HashMap::new())),
_open_rx,
open_tx,
monitor_state,
Expand Down Expand Up @@ -259,7 +254,7 @@ impl WidgetFactory {
}

let webview_url = WebviewUrl::External(
create_init_url(self, &parent_dir, &html_path).await?,
create_init_url(&parent_dir, &html_path).await?,
);

let mut state = WidgetState {
Expand Down Expand Up @@ -811,40 +806,4 @@ impl WidgetFactory {
},
)
}

/// Returns an asset server token for a given directory.
///
/// If the directory does not have an existing token, a new one is
/// generated and inserted.
pub async fn upsert_or_get_token(&self, directory: &Path) -> String {
let mut asset_server_tokens = self.asset_server_tokens.lock().await;

// Find existing token for this path.
let found_token = asset_server_tokens
.iter()
.find(|(_, path)| *path == directory)
.map(|(token, _)| token.clone());

found_token.unwrap_or_else(|| {
let new_token = Uuid::new_v4().to_string();

asset_server_tokens
.insert(new_token.clone(), directory.to_path_buf());

new_token
})
}

/// Returns the base directory for a given asset server token.
pub async fn directory_by_token(
&self,
asset_server_token: &str,
) -> Option<PathBuf> {
self
.asset_server_tokens
.lock()
.await
.get(asset_server_token)
.cloned()
}
}

0 comments on commit c15d322

Please sign in to comment.