Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite tauri_plugin_localhost to fix Linux resource loading issues #39

Merged
merged 5 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bins/ayaka-gui/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ flexi_logger = { version = "0.24", default-features = false, features = ["colors
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2", features = ["cli", "protocol-all", "window-all"] }
tauri-plugin-localhost = "0.1"
tiny_http = "0.12"
minreq = "2.6"
mime_guess = "2.0"
portpicker = "0.1"
trylog = "0.2"

Expand Down
108 changes: 108 additions & 0 deletions bins/ayaka-gui/src-tauri/src/asset_resolver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use tauri::{
plugin::{Builder, TauriPlugin},
Runtime,
};
use tiny_http::{Header, Server};

pub fn init<R: Runtime>(dev_url: String, port: u16) -> TauriPlugin<R> {
Builder::new("asset_resolver")
.setup(move |app| {
let asset_resolver = app.asset_resolver();
std::thread::spawn(move || {
let server = Server::http(format!("127.0.0.1:{port}"))
.expect("Unable to start local server");
for req in server.incoming_requests() {
#[cfg(debug_assertions)]
Berrysoft marked this conversation as resolved.
Show resolved Hide resolved
let _ = asset_resolver;
#[cfg(not(debug_assertions))]
if req.url().starts_with("/assets/")
Berrysoft marked this conversation as resolved.
Show resolved Hide resolved
|| req.url() == "/"
|| req.url() == "/live2d.min.js"
|| req.url() == "/live2dcubismcore.min.js"
{
let asset = asset_resolver.get(req.url().into()).unwrap();
let mut resp = if let Some(csp) = asset.csp_header {
Berrysoft marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(target_os = "linux")]
let mut resp = {
let html = String::from_utf8_lossy(&asset.bytes);
let body = html.replacen(tauri::utils::html::CSP_TOKEN, &csp, 1);
tiny_http::Response::from_data(body)
};
#[cfg(not(target_os = "linux"))]
let mut resp = Response::from_data(asset.bytes);
Berrysoft marked this conversation as resolved.
Show resolved Hide resolved
resp.add_header(
Header::from_bytes("Content-Security-Policy", csp).expect(
"Unable to convert csp_header to Content-Security-Policy",
),
);
resp
} else {
tiny_http::Response::from_data(asset.bytes)
};
resp.add_header(
Header::from_bytes("Content-Type", asset.mime_type)
.expect("Unable to convert mime_type to Content-Type"),
);
req.respond(resp).expect("Unable to setup response");
continue;
}
match (req.url(), std::fs::canonicalize(req.url())) {
Berrysoft marked this conversation as resolved.
Show resolved Hide resolved
("/", _) | (_, Err(_)) => {
#[cfg(debug_assertions)]
{
let path = if req.url().ends_with('/') {
Tim-Paik marked this conversation as resolved.
Show resolved Hide resolved
req.url().to_string() + "index.html"
} else {
req.url().to_string()
};
let resp =
minreq::get(dev_url.trim_end_matches('/').to_string() + &path)
Tim-Paik marked this conversation as resolved.
Show resolved Hide resolved
.send()
.expect("Unable to send request");
req.respond(tiny_http::Response::new(
resp.status_code.into(),
resp.headers
.iter()
.map(|(k, v)| {
Header::from_bytes(k.as_bytes(), v.as_bytes())
.expect("Unable to convert Header")
})
.collect(),
resp.as_bytes(),
None,
None,
))
.expect("Unable to setup response")
}
#[cfg(not(debug_assertions))]
{
let _ = dev_url;
req.respond(tiny_http::Response::empty(404))
.expect("Unable to setup response")
}
}
(_, Ok(path)) => {
let file = std::fs::File::open(&path).unwrap();
let file = if file.metadata().unwrap().is_dir() {
Berrysoft marked this conversation as resolved.
Show resolved Hide resolved
let mut path = path.clone();
path.push("index.html");
std::fs::File::open(path).unwrap()
} else {
file
};
let mut resp = tiny_http::Response::from_file(file);
if let Some(mime) = mime_guess::from_path(req.url()).first() {
resp.add_header(
Header::from_bytes("Content-Type", mime.essence_str())
.expect("Unable to convert mime_type to Content-Type"),
);
}
req.respond(resp).expect("Unable to setup response")
}
};
}
});
Ok(())
})
.build()
}
17 changes: 13 additions & 4 deletions bins/ayaka-gui/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
)]
#![feature(absolute_path)]
Tim-Paik marked this conversation as resolved.
Show resolved Hide resolved

mod asset_resolver;

use ayaka_runtime::{
anyhow::{self, anyhow, Result},
log::{debug, info},
Expand All @@ -16,7 +18,9 @@ use std::{
fmt::Display,
path::PathBuf,
};
use tauri::{async_runtime::Mutex, command, AppHandle, Manager, State};
use tauri::{
async_runtime::Mutex, command, utils::config::AppUrl, AppHandle, Manager, State, WindowUrl,
};
use trylog::TryLog;

type CommandResult<T> = std::result::Result<T, CommandError>;
Expand Down Expand Up @@ -426,9 +430,14 @@ fn main() -> Result<()> {
let port =
portpicker::pick_unused_port().ok_or_else(|| anyhow!("failed to find unused port"))?;
info!("Picked port {}", port);
let mut context = tauri::generate_context!();
let window_url = WindowUrl::External(format!("http://127.0.0.1:{port}").parse().unwrap());
let dev_url = context.config().build.dev_path.to_string();
context.config_mut().build.dist_dir = AppUrl::Url(window_url.clone());
context.config_mut().build.dev_path = AppUrl::Url(window_url);
tauri::Builder::default()
.plugin(tauri_plugin_localhost::Builder::new(port).build())
.setup(|app| {
.plugin(asset_resolver::init(dev_url, port))
.setup(move |app| {
let ident = app.config().tauri.bundle.identifier.clone();
let spec = LogSpecification::parse("warn,ayaka=debug")?;
let log_handle = if cfg!(debug_assertions) {
Expand Down Expand Up @@ -493,6 +502,6 @@ fn main() -> Result<()> {
switch,
history,
])
.run(tauri::generate_context!())?;
.run(context)?;
Ok(())
}
4 changes: 2 additions & 2 deletions bins/ayaka-gui/src/interop/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { convertFileSrc, invoke } from "@tauri-apps/api/tauri"
import { invoke } from "@tauri-apps/api/tauri"
import { Locale } from 'vue-i18n'

export async function conv_src(path?: string): Promise<string | undefined> {
if (path) {
return decodeURIComponent(convertFileSrc(await invoke("absolute_path", { path: path })))
return decodeURIComponent(await invoke("absolute_path", { path: path }))
}
return undefined
}
Expand Down