# Stash Stash 是一个基于 Rust、Tokio 和 Axum 实现的本地静态页面托管工具。它既可以直接托管一个静态站点,也可以扫描托管目录下的多个前端项目,并通过内置导航页统一访问。 ## 核心功能 ### 单站点托管 当托管根目录中存在 `index.html` 时,访问 `/` 会直接返回该页面。页面依赖的 JavaScript、CSS、图片、字体等资源继续通过静态文件服务加载,因此可以直接运行常见的纯静态前端项目。 ### 多项目导航 当根目录没有 `index.html` 时,Stash 会扫描根目录下的一级子目录,并将包含 `index.html` 或 `index.htm` 的目录识别为前端项目。 - 自动排除以 `.` 开头的隐藏目录。 - 项目按名称进行不区分大小写的升序排列。 - 每个项目生成一个卡片链接,地址格式为 `/<项目目录名>/`。 - 项目名称首字符会作为圆形标记显示。 - 没有识别到项目时显示空状态提示。 - 导航页采用 4 列、2 列、1 列的响应式布局,分别适配桌面、平板和手机。 - 项目和目录列表在每次请求时重新扫描,新增项目通常无需重启服务。 - 文件监听会在项目快照发生变化后主动通知已打开的导航页,无需手动刷新。 ### 静态文件服务 Stash 使用 `tower-http` 的 `ServeDir` 托管根目录内容: - 自动为目录追加 `index.html`。 - 根据文件扩展名返回对应的 MIME 类型。 - 未找到的路径会返回内置的中文 404 页面,并显示请求路径。 - 每次 HTTP 请求都会经过 Trace 层,可通过调整日志级别观察请求日志。 - 内置控制台资源通过保留路径 `/__stash__/` 提供,避免与用户托管的项目文件冲突。 ### 内置控制台 - 使用 Askama 在编译期渲染项目导航页和 404 页面。 - 页面 HTML、CSS 和 JavaScript 分别维护,不再使用字符串替换拼接卡片。 - 项目名称和请求路径由模板引擎自动进行 HTML 转义。 - 项目目录名会进行 URL 路径段编码,再生成项目访问地址。 - 少量 JavaScript 通过 SSE 订阅项目变化,并在不刷新整个页面的情况下更新卡片;脚本不可用时,服务端渲染的导航和手动 API 仍可正常使用。 ### 同源 API 服务提供两个只读 JSON 接口和一个 SSE 推送接口,可供导航页或同源前端调用。 ### CORS 默认允许任意来源、任意请求方法和任意请求头访问服务,适合本地联调。通过 `--no-cors` 可以关闭 CORS 标头注入。 ### 服务管理 - 默认监听 `127.0.0.1:8080`。 - 支持自定义绑定地址、端口和托管目录。 - 默认托管目录 `./public` 不存在时会自动创建。 - 用户显式指定的托管目录不存在时,会输出错误并退出。 - 端口绑定失败、目录无效等错误会以清晰的错误信息返回。 - 支持分别通过 `Ctrl+C` 以及 Unix 系统的 `SIGTERM` 触发优雅停机。 ### 可复用核心库 `stash-core` 同时作为库导出 `Config`、`StashError`、`start`、`ServerHandle`、`scan_projects` 和 `AppProject`,既可由 `stash-cli` 使用,也可以被其他 Rust 程序嵌入或复用。 ## 快速开始 ### 环境要求 - Rust 工具链,需支持 Rust 2024 Edition。 - Cargo。 ### 启动示例 ```bash # 托管默认目录 ./public,监听 127.0.0.1:8080 cargo run -p stash-cli # 托管指定目录并修改端口 cargo run -p stash-cli -- --root ./sites --port 3000 # 允许局域网设备访问 cargo run -p stash-cli -- --root ./sites --host 0.0.0.0 --port 3000 # 关闭 CORS cargo run -p stash-cli -- --root ./sites --no-cors ``` 启动成功后访问终端中显示的地址即可,例如: ```text http://127.0.0.1:8080/ ``` ### 构建发布版本 ```bash cargo build --release -p stash-cli ``` 构建产物为 `target/release/stash`;Windows 下为 `target/release/stash.exe`。 ## 托管目录示例 ### 单个静态站点 ```text public/ ├── index.html ├── assets/ │ ├── app.js │ └── style.css └── images/ └── logo.png ``` 此时访问 `/` 会直接展示 `public/index.html`。 ### 多个前端项目 ```text public/ ├── admin-console/ │ └── index.html ├── docs/ │ └── index.html └── landing-page/ └── index.html ``` 由于根目录没有 `index.html`,访问 `/` 时会展示项目导航页。对应访问地址为: ```text /admin-console/ /docs/ /landing-page/ ``` ## 命令行参数 | 参数 | 默认值 | 说明 | | --- | --- | --- | | `-r, --root