exum 0.1.14

A lightweight Axum syntax sugar library
Documentation
# 静态文件服务

Exum 提供了强大的静态文件服务,基于 `StaticFileServiceBuilder` 构建,支持多种高级特性。

## 功能特性

### 🌐 跨域支持
- **CORS配置** - 支持完整的CORS跨域配置
- **预置CORS策略** - 提供 `cors_any()` 方法快速启用全允许CORS

### 📱 SPA支持
- **SPA回退** - 支持单页应用的回退机制,未找到文件时返回 `index.html`
- **智能路由** - 适合Vue、React等前端框架的单页应用部署

### 📊 文件处理
- **流式传输** - 使用 `tokio_util::io::ReaderStream` 实现高效的文件流传输
- **MIME类型推测** - 自动根据文件扩展名推测正确的MIME类型
- **UTF-8字符集** - 对文本文件自动添加 `charset=utf-8` 字符集
- **Last-Modified头** - 自动添加文件修改时间,支持浏览器缓存
- **HEAD请求支持** - 正确处理HEAD请求,返回文件元信息

### 🔧 错误处理
- **智能404处理** - 文件不存在时返回适当的404响应
- **错误日志** - 使用tracing记录服务错误信息

## 使用 StaticFileServiceBuilder

### 基础用法

```rust
use exum::layers::StaticFileServiceBuilder;

#[tokio::main]
async fn main() {
    let static_service = StaticFileServiceBuilder::new("./public")
        .build_router("/static");
    
    let mut app = Application::build(ApplicationConfig::default());
    app.merge(static_service);
    
    app.run().await;
}
```

### 启用SPA回退

```rust
use exum::layers::StaticFileServiceBuilder;

#[tokio::main]
async fn main() {
    let static_service = StaticFileServiceBuilder::new("./public")
        .with_spa_fallback(true)  // 启用SPA回退
        .build_router("/static");
    
    let mut app = Application::build(ApplicationConfig::default());
    app.merge(static_service);
    
    app.run().await;
}
```

### 启用CORS支持

```rust
use exum::layers::StaticFileServiceBuilder;

#[tokio::main]
async fn main() {
    let static_service = StaticFileServiceBuilder::new("./public")
        .cors_any()  // 启用全允许CORS
        .build_router("/static");
    
    let mut app = Application::build(ApplicationConfig::default());
    app.merge(static_service);
    
    app.run().await;
}
```

### 完整配置示例

```rust
use exum::layers::StaticFileServiceBuilder;

#[tokio::main]
async fn main() {
    let static_service = StaticFileServiceBuilder::new("./public")
        .with_spa_fallback(true)  // 启用SPA回退
        .cors_any()               // 启用CORS跨域支持
        .build_router("/assets");
    
    let mut app = Application::build(ApplicationConfig::default());
    app.merge(static_service);
    
    app.run().await;
}
```

## 基础静态文件服务(需要 app_chain_ext_full 特性)

> **注意**`static_` 方法使用的是基础的 `tower_http::services::ServeDir` 服务,体验不如 `StaticFileServiceBuilder`,例如不支持自动URL编码路径、SPA回退等高级功能。建议优先使用 `StaticFileServiceBuilder`
```rust
use exum::*;

#[tokio::main]
async fn main() {
    let mut app = Application::build(ApplicationConfig::default());
    app.static_("/static", "./public");
    
    app.run().await;
}
```



## 最佳实践

1. **优先使用StaticFileServiceBuilder** - 相比基础的 `static_` 方法,提供更多高级功能
2. **生产环境启用SPA回退** - 适合部署单页应用
3. **开发环境启用CORS** - 方便前后端分离开发
4. **使用相对路径** - 服务会自动解析为绝对路径,确保安全性