289 lines
7.5 KiB
Markdown
289 lines
7.5 KiB
Markdown
## Trie 路由树(高性能路由)
|
||
|
||
### 简介
|
||
Trie 路由树是一种高性能的路由匹配结构,广泛应用于现代 Web 框架。相比传统的正则遍历路由,Trie 路由树在大规模路由和高并发场景下具有更高的查找效率。
|
||
|
||
### 特性
|
||
- 支持静态路由、命名参数(如 `/user/:id`)、通配符(如 `/static/*filepath`)
|
||
- 支持正则路由(如 `/user/(?P<id>[^/]+)`),正则路由单独分流
|
||
- 路由树根节点按 HTTP 方法(GET/POST/PUT/DELETE)分流,进一步提升查找效率
|
||
- 内置 LRU 路由缓存,热点路由命中极快
|
||
- 性能测试显示 Trie 路由树在大规模动态路由下性能优于传统正则遍历
|
||
|
||
### 用法
|
||
注册路由时,框架会自动将路由注册到 Trie 路由树和 HybridRouter:
|
||
|
||
```v
|
||
app.get('/api/users/:id', fn (req hono.Request) http.Response {
|
||
return hono.Response.json('{"user_id": "${req.param["id"]}"}')
|
||
})
|
||
```
|
||
|
||
### 性能优势
|
||
- 静态路由、参数路由、通配符路由查找均为 O(n)(n为路径层级),极快
|
||
- 路由缓存命中时,查找仅需一次 map 查询,QPS 可达 20~30 万
|
||
- 支持上千条动态路由、百万级请求高并发场景
|
||
|
||
### 缓存说明
|
||
- Trie 路由树内置 LRU 缓存(默认容量1000),缓存 key 为 `method:path`,value 为 `RouteMatch`
|
||
- 命中缓存时性能极高,未命中时自动查找并写入缓存
|
||
- 可根据实际需求调整缓存容量
|
||
|
||
### 与 HybridRouter 对比
|
||
- HybridRouter 采用静态路由 map + 动态正则遍历,适合路由数量较少或兼容性需求高的场景
|
||
- TrieRouter 适合大规模路由、高并发、极致性能场景
|
||
- 两者可并存,便于灵活切换和对比测试
|
||
|
||
---
|
||
|
||
# 静态文件服务中间件
|
||
|
||
## 概述
|
||
|
||
为 V-Hono 框架添加了类似 Hono.js 的 `serveStatic` 中间件,提供高效、安全的静态文件服务功能。
|
||
|
||
## 实现文件
|
||
|
||
### 核心实现
|
||
- `hono/static.v` - 静态文件服务中间件的主要实现
|
||
|
||
### 示例文件
|
||
- `example.v` - 包含静态文件服务的完整示例
|
||
|
||
### 测试文件
|
||
- `public/index.html` - 默认索引文件
|
||
- `public/test.txt` - 测试文本文件
|
||
- `static/style.css` - 测试CSS文件
|
||
- `static/app.js` - 测试JavaScript文件
|
||
- `uploads/sample.json` - 测试JSON文件
|
||
|
||
## 核心功能
|
||
|
||
### 1. 静态文件服务中间件 (`serve_static`)
|
||
|
||
```v
|
||
pub fn serve_static(options StaticOptions) fn (mut Context, fn (mut Context) http.Response) http.Response
|
||
```
|
||
|
||
主要特性:
|
||
- 路径匹配和文件映射
|
||
- 安全检查(路径遍历攻击防护)
|
||
- 点文件访问控制
|
||
- 自动索引文件支持
|
||
- 智能错误处理
|
||
|
||
### 2. 配置选项 (`StaticOptions`)
|
||
|
||
```v
|
||
pub struct StaticOptions {
|
||
pub:
|
||
root string = './public' // 静态文件根目录
|
||
path string = '/' // URL路径前缀
|
||
index string = 'index.html' // 默认索引文件
|
||
dotfiles bool = false // 是否允许访问以.开头的文件
|
||
etag bool = true // 是否启用ETag
|
||
last_modified bool = true // 是否启用Last-Modified
|
||
max_age int = 0 // 缓存时间(秒)
|
||
headers map[string]string // 自定义响应头
|
||
}
|
||
```
|
||
|
||
### 3. 便捷函数
|
||
|
||
- `serve_static_default()` - 使用默认配置
|
||
- `serve_static_root(root string)` - 指定根目录
|
||
- `serve_static_path(path string, root string)` - 指定路径前缀和根目录
|
||
|
||
## 安全特性
|
||
|
||
### 路径遍历攻击防护
|
||
|
||
```v
|
||
fn is_safe_path(path string) bool {
|
||
// 检查是否包含 .. 或绝对路径
|
||
if path.contains('..') || path.starts_with('/') || path.starts_with('\\') {
|
||
return false
|
||
}
|
||
|
||
// 检查是否包含危险字符
|
||
dangerous_chars := ['<', '>', ':', '"', '|', '?', '*']
|
||
for char in dangerous_chars {
|
||
if path.contains(char) {
|
||
return false
|
||
}
|
||
}
|
||
|
||
return true
|
||
}
|
||
```
|
||
|
||
### 点文件访问控制
|
||
|
||
默认情况下阻止访问以 `.` 开头的文件,可通过 `dotfiles: true` 启用。
|
||
|
||
## 性能特性
|
||
|
||
### ETag 支持
|
||
|
||
```v
|
||
fn generate_etag(content string, mod_time i64) string {
|
||
return '"${content.len}-${mod_time}"'
|
||
}
|
||
```
|
||
|
||
### 缓存控制
|
||
|
||
```v
|
||
if options.max_age > 0 {
|
||
c.headers['Cache-Control'] = 'public, max-age=${options.max_age}'
|
||
} else {
|
||
c.headers['Cache-Control'] = 'no-cache'
|
||
}
|
||
```
|
||
|
||
### Content-Type 检测
|
||
|
||
支持30+种文件类型的自动Content-Type检测:
|
||
|
||
```v
|
||
fn get_content_type(file_path string) string {
|
||
ext := os.file_ext(file_path).to_lower()
|
||
|
||
match ext {
|
||
'.html', '.htm' { return 'text/html; charset=utf-8' }
|
||
'.css' { return 'text/css; charset=utf-8' }
|
||
'.js' { return 'application/javascript; charset=utf-8' }
|
||
'.json' { return 'application/json; charset=utf-8' }
|
||
// ... 更多类型
|
||
else { return 'application/octet-stream' }
|
||
}
|
||
}
|
||
```
|
||
|
||
## 使用示例
|
||
|
||
### 基本用法
|
||
|
||
```v
|
||
import hono
|
||
|
||
mut app := hono.new_hono()
|
||
|
||
// 使用默认配置
|
||
app.use(hono.serve_static_default())
|
||
|
||
app.listen(':8080')
|
||
```
|
||
|
||
### 多目录配置
|
||
|
||
```v
|
||
// 默认静态文件
|
||
app.use(hono.serve_static_default())
|
||
|
||
// 资源文件
|
||
app.use(hono.serve_static_path('/assets', './static'))
|
||
|
||
// 上传文件
|
||
app.use(hono.serve_static_path('/uploads', './uploads'))
|
||
```
|
||
|
||
### 自定义配置
|
||
|
||
```v
|
||
options := hono.StaticOptions{
|
||
root: './public'
|
||
path: '/static'
|
||
index: 'index.html'
|
||
dotfiles: false
|
||
etag: true
|
||
last_modified: true
|
||
max_age: 3600
|
||
headers: {
|
||
'X-Served-By': 'V-Hono'
|
||
}
|
||
}
|
||
|
||
app.use(hono.serve_static(options))
|
||
```
|
||
|
||
## 与 Hono.js 的对比
|
||
|
||
| 特性 | V-Hono | Hono.js |
|
||
|------|--------|---------|
|
||
| 路径遍历防护 | ✅ | ✅ |
|
||
| 点文件控制 | ✅ | ✅ |
|
||
| ETag 支持 | ✅ | ✅ |
|
||
| Last-Modified | ✅ | ✅ |
|
||
| 缓存控制 | ✅ | ✅ |
|
||
| 自定义头部 | ✅ | ✅ |
|
||
| 自动索引文件 | ✅ | ✅ |
|
||
| Content-Type 检测 | ✅ | ✅ |
|
||
| 多目录支持 | ✅ | ✅ |
|
||
|
||
## 测试和验证
|
||
|
||
### 运行测试
|
||
|
||
```bash
|
||
# 完整示例
|
||
v run example.v
|
||
```
|
||
|
||
### 测试用例
|
||
|
||
1. **基本文件服务**
|
||
- 访问 `public/test.txt` → `/test.txt`
|
||
- 访问 `static/style.css` → `/assets/style.css`
|
||
|
||
2. **索引文件**
|
||
- 访问目录 `/` → 提供 `public/index.html`
|
||
|
||
3. **安全测试**
|
||
- 尝试路径遍历攻击 → 返回 403 Forbidden
|
||
- 尝试访问点文件 → 返回 403 Forbidden
|
||
|
||
4. **缓存测试**
|
||
- 检查 ETag 头
|
||
- 检查 Last-Modified 头
|
||
- 检查 Cache-Control 头
|
||
|
||
5. **Content-Type 测试**
|
||
- 验证不同文件类型的正确 Content-Type
|
||
|
||
## 性能考虑
|
||
|
||
### 优化点
|
||
|
||
1. **文件读取**: 使用 V 语言的 `os.read_file()` 进行高效文件读取
|
||
2. **路径检查**: 快速的安全路径验证
|
||
3. **头部生成**: 高效的响应头构建
|
||
4. **缓存策略**: 可配置的缓存控制
|
||
|
||
### 内存使用
|
||
|
||
- 文件内容一次性读取到内存
|
||
- 适合中小型文件
|
||
- 大文件建议使用专门的CDN服务
|
||
|
||
## 未来改进
|
||
|
||
### 可能的增强
|
||
|
||
1. **流式文件服务**: 支持大文件的流式传输
|
||
2. **压缩支持**: 自动Gzip压缩
|
||
3. **范围请求**: 支持HTTP Range请求
|
||
4. **文件监控**: 文件变化时自动刷新缓存
|
||
5. **性能监控**: 添加性能指标收集
|
||
|
||
### 扩展性
|
||
|
||
当前实现具有良好的扩展性,可以轻松添加:
|
||
- 新的文件类型支持
|
||
- 自定义安全检查
|
||
- 更多的缓存策略
|
||
- 文件预处理功能
|
||
|
||
## 总结
|
||
|
||
成功为 V-Hono 框架添加了功能完整、安全可靠的静态文件服务中间件,提供了与 Hono.js 相当的体验,同时充分利用了 V 语言的特性。该实现具有良好的安全性、性能和易用性,可以满足大多数Web应用的静态文件服务需求。 |