snapshot of https://github.com/tauri-apps/tauri.git (dev, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
This commit is contained in:
169
crates/tauri-cli/src/dev/builtin_dev_server.rs
Normal file
169
crates/tauri-cli/src/dev/builtin_dev_server.rs
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use axum::{
|
||||
extract::{State, WebSocketUpgrade, ws},
|
||||
http::{StatusCode, Uri, header},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use std::{
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use tauri_utils::mime_type::MimeType;
|
||||
use tokio::sync::broadcast::{Sender, channel};
|
||||
|
||||
use crate::error::ErrorExt;
|
||||
|
||||
const RELOAD_SCRIPT: &str = include_str!("./auto-reload.js");
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ServerState {
|
||||
dir: PathBuf,
|
||||
address: SocketAddr,
|
||||
tx: Sender<()>,
|
||||
}
|
||||
|
||||
pub fn start<P: AsRef<Path>>(dir: P, ip: IpAddr, port: Option<u16>) -> crate::Result<SocketAddr> {
|
||||
let dir = dir.as_ref();
|
||||
let dir =
|
||||
dunce::canonicalize(dir).fs_context("failed to canonicalize path", dir.to_path_buf())?;
|
||||
|
||||
// bind port and tcp listener
|
||||
let auto_port = port.is_none();
|
||||
let mut port = port.unwrap_or(1430);
|
||||
let (tcp_listener, address) = loop {
|
||||
let address = SocketAddr::new(ip, port);
|
||||
if let Ok(tcp) = std::net::TcpListener::bind(address) {
|
||||
tcp.set_nonblocking(true).unwrap();
|
||||
break (tcp, address);
|
||||
}
|
||||
|
||||
if !auto_port {
|
||||
crate::error::bail!("Couldn't bind to {port} on {ip}");
|
||||
}
|
||||
|
||||
port += 1;
|
||||
};
|
||||
|
||||
let (tx, _) = channel(1);
|
||||
|
||||
// watch dir for changes
|
||||
let tx_c = tx.clone();
|
||||
watch(dir.clone(), move || {
|
||||
let _ = tx_c.send(());
|
||||
});
|
||||
|
||||
let state = ServerState { dir, tx, address };
|
||||
|
||||
// start router thread
|
||||
std::thread::spawn(move || {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
.build()
|
||||
.expect("failed to start tokio runtime for builtin dev server")
|
||||
.block_on(async move {
|
||||
let router = axum::Router::new()
|
||||
.fallback(handler)
|
||||
.route("/__tauri_cli", axum::routing::get(ws_handler))
|
||||
.with_state(state);
|
||||
|
||||
axum::serve(tokio::net::TcpListener::from_std(tcp_listener)?, router).await
|
||||
})
|
||||
.expect("builtin server errored");
|
||||
});
|
||||
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
async fn handler(uri: Uri, state: State<ServerState>) -> impl IntoResponse {
|
||||
// Frontend files should not contain query parameters. This seems to be how Vite handles it.
|
||||
let uri = uri.path();
|
||||
|
||||
let uri = if uri == "/" {
|
||||
uri
|
||||
} else {
|
||||
uri.strip_prefix('/').unwrap_or(uri)
|
||||
};
|
||||
|
||||
let bytes = fs_read_scoped(state.dir.join(uri), &state.dir)
|
||||
.or_else(|_| fs_read_scoped(state.dir.join(format!("{uri}.html")), &state.dir))
|
||||
.or_else(|_| fs_read_scoped(state.dir.join(format!("{uri}/index.html")), &state.dir))
|
||||
.or_else(|_| std::fs::read(state.dir.join("index.html")));
|
||||
|
||||
match bytes {
|
||||
Ok(mut bytes) => {
|
||||
let mime_type = MimeType::parse_with_fallback(&bytes, uri, MimeType::OctetStream);
|
||||
if mime_type == MimeType::Html.to_string() {
|
||||
bytes = inject_address(bytes, &state.address);
|
||||
}
|
||||
(StatusCode::OK, [(header::CONTENT_TYPE, mime_type)], bytes)
|
||||
}
|
||||
Err(_) => (
|
||||
StatusCode::NOT_FOUND,
|
||||
[(header::CONTENT_TYPE, "text/plain".into())],
|
||||
vec![],
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
async fn ws_handler(ws: WebSocketUpgrade, state: State<ServerState>) -> Response {
|
||||
ws.on_upgrade(move |mut ws| async move {
|
||||
let mut rx = state.tx.subscribe();
|
||||
while tokio::select! {
|
||||
_ = ws.recv() => return,
|
||||
fs_reload_event = rx.recv() => fs_reload_event.is_ok(),
|
||||
} {
|
||||
let msg = ws::Message::Text(r#"{"reload": true}"#.into());
|
||||
if ws.send(msg).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn inject_address(html_bytes: Vec<u8>, address: &SocketAddr) -> Vec<u8> {
|
||||
let document = tauri_utils::html2::parse_doc(String::from_utf8_lossy(&html_bytes).into_owned());
|
||||
|
||||
tauri_utils::html2::append_script_to_head(
|
||||
&document,
|
||||
&RELOAD_SCRIPT.replace("{{reload_url}}", &format!("ws://{address}/__tauri_cli")),
|
||||
);
|
||||
|
||||
tauri_utils::html2::serialize_doc(&document)
|
||||
}
|
||||
|
||||
fn fs_read_scoped(path: PathBuf, scope: &Path) -> crate::Result<Vec<u8>> {
|
||||
let path = dunce::canonicalize(&path).fs_context("failed to canonicalize path", path)?;
|
||||
if path.starts_with(scope) {
|
||||
std::fs::read(&path).fs_context("failed to read file", &path)
|
||||
} else {
|
||||
crate::error::bail!("forbidden path")
|
||||
}
|
||||
}
|
||||
|
||||
fn watch<F: Fn() + Send + 'static>(dir: PathBuf, handler: F) {
|
||||
thread::spawn(move || {
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut watcher = notify_debouncer_full::new_debouncer(Duration::from_secs(1), None, tx)
|
||||
.expect("failed to start builtin server fs watcher");
|
||||
|
||||
watcher
|
||||
.watch(&dir, notify::RecursiveMode::Recursive)
|
||||
.expect("builtin server failed to watch dir");
|
||||
|
||||
loop {
|
||||
if let Ok(Ok(event)) = rx.recv() {
|
||||
if let Some(event) = event.first() {
|
||||
if !event.kind.is_access() {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user