mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-03-15 07:26:44 +08:00
feat(video): 事务化切换与前端统一编排,增强视频输入格式支持
- 后端:切换事务+transition_id,/stream/mode 返回 switching/transition_id 与实际 codec - 事件:新增 mode_switching/mode_ready,config/webrtc_ready/mode_changed 关联事务 - 编码/格式:扩展 NV21/NV16/NV24/RGB/BGR 输入与转换链路,RKMPP direct input 优化 - 前端:useVideoSession 统一切换,失败回退真实切回 MJPEG,菜单格式同步修复 - 清理:useVideoStream 降级为 MJPEG-only
This commit is contained in:
@@ -26,16 +26,18 @@ pub struct StaticAssets;
|
||||
#[cfg(debug_assertions)]
|
||||
fn get_static_base_dir() -> PathBuf {
|
||||
static BASE_DIR: OnceLock<PathBuf> = OnceLock::new();
|
||||
BASE_DIR.get_or_init(|| {
|
||||
// Try to get executable directory
|
||||
if let Ok(exe_path) = std::env::current_exe() {
|
||||
if let Some(exe_dir) = exe_path.parent() {
|
||||
return exe_dir.join("web").join("dist");
|
||||
BASE_DIR
|
||||
.get_or_init(|| {
|
||||
// Try to get executable directory
|
||||
if let Ok(exe_path) = std::env::current_exe() {
|
||||
if let Some(exe_dir) = exe_path.parent() {
|
||||
return exe_dir.join("web").join("dist");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback to current directory
|
||||
PathBuf::from("web/dist")
|
||||
}).clone()
|
||||
// Fallback to current directory
|
||||
PathBuf::from("web/dist")
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Create router for static file serving
|
||||
@@ -102,29 +104,29 @@ fn try_serve_file(path: &str) -> Option<Response<Body>> {
|
||||
// Debug mode: read from file system
|
||||
let base_dir = get_static_base_dir();
|
||||
let file_path = base_dir.join(path);
|
||||
|
||||
|
||||
// Check if file exists and is within base directory (prevent directory traversal)
|
||||
if !file_path.starts_with(&base_dir) {
|
||||
tracing::warn!("Path traversal attempt blocked: {}", path);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
// Normalize path to prevent directory traversal (only if file exists)
|
||||
if let (Ok(normalized_path), Ok(normalized_base)) =
|
||||
(file_path.canonicalize(), base_dir.canonicalize())
|
||||
if let (Ok(normalized_path), Ok(normalized_base)) =
|
||||
(file_path.canonicalize(), base_dir.canonicalize())
|
||||
{
|
||||
if !normalized_path.starts_with(&normalized_base) {
|
||||
tracing::warn!("Path traversal attempt blocked (canonicalized): {}", path);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
match std::fs::read(&file_path) {
|
||||
Ok(data) => {
|
||||
let mime = mime_guess::from_path(path)
|
||||
.first_or_octet_stream()
|
||||
.to_string();
|
||||
|
||||
|
||||
return Some(
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
@@ -145,16 +147,16 @@ fn try_serve_file(path: &str) -> Option<Response<Body>> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
// Release mode: use embedded assets
|
||||
let asset = StaticAssets::get(path)?;
|
||||
|
||||
|
||||
let mime = mime_guess::from_path(path)
|
||||
.first_or_octet_stream()
|
||||
.to_string();
|
||||
|
||||
|
||||
Some(
|
||||
Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
|
||||
Reference in New Issue
Block a user