Files
v-hono/README.MD
T

377 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# V-Hono
一个用 V 语言编写的轻量级 Web 框架,灵感来自 Hono.js。
## 特性
- 🚀 高性能路由系统(混合路由算法)
- 🎯 类似 Hono.js 的 Context API
- 🔧 洋葱模型中间件支持
- 📦 内置 LRU 缓存系统
- 🛠️ 支持动态路由参数(`:param`)
- ⚡ 支持通配符路由(`*` 和 `**`)
- 🔄 支持所有 HTTP 方法(GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS)
- 🏗️ 构造函数风格的 API 设计
- 📁 静态文件服务中间件(类似 Hono.js 的 serveStatic)
- 🛡️ 内置安全防护(路径遍历攻击防护、点文件访问控制)
- 💾 智能缓存支持(ETag、Last-Modified、Cache-Control)
- 🎯 自动 Content-Type 检测
## 安装
```bash
# 克隆仓库
git clone https://github.com/your-username/v-hono.git
cd v-hono
# 运行示例
v run example.v
```
## 快速开始
```v
module main
import hono
import net.http
fn main() {
mut app := hono.Hono.new()
// 基本路由
app.get('/', fn (mut c hono.Context) http.Response {
return c.html('<h1>Hello V-Hono!</h1>')
})
app.get('/api/users/:id', fn (mut c hono.Context) http.Response {
user_id := c.params['id']
return c.json('{"id": "${user_id}", "name": "John Doe"}')
})
app.post('/api/users', fn (mut c hono.Context) http.Response {
c.status(201)
return c.json('{"message": "User created", "data": "${c.body}"}')
})
// 中间件
app.use(fn (mut c hono.Context, next fn (mut hono.Context) http.Response) http.Response {
println('[LOG] ${c.url}')
return next(mut c)
})
app.listen(':3000')
}
```
## API 参考
### Context
Context 是请求的核心对象,包含所有请求和响应信息:
```v
pub struct Context {
pub:
req http.Request // 原始 HTTP 请求
params map[string]string // 路径参数
query map[string]string // 查询参数
url string // 请求 URL
pub mut:
status_code int = 200 // 响应状态码
headers map[string]string // 响应头
body string // 响应体
}
```
### 构造函数
所有对象都使用构造函数风格创建:
```v
// 创建 Context
ctx := hono.Context.new(req, params, query, body)
// 创建路由器
router := hono.ContextHybridRouter.new()
trie_router := hono.ContextTrieRouter.new()
// 创建缓存
cache := hono.ContextLRUCache.new(1000)
```
### 路由方法
支持所有 HTTP 方法:
```v
// GET 请求
app.get('/path', fn (mut c hono.Context) http.Response {
return c.json('{"message": "GET response"}')
})
// POST 请求
app.post('/path', fn (mut c hono.Context) http.Response {
return c.json('{"message": "POST response"}')
})
// PUT 请求
app.put('/path', fn (mut c hono.Context) http.Response {
return c.json('{"message": "PUT response"}')
})
// DELETE 请求
app.delete('/path', fn (mut c hono.Context) http.Response {
c.status(204)
return c.text('')
})
// PATCH 请求
app.patch('/path', fn (mut c hono.Context) http.Response {
return c.json('{"message": "PATCH response"}')
})
// HEAD 请求
app.head('/path', fn (mut c hono.Context) http.Response {
return c.text('')
})
// OPTIONS 请求
app.options('/path', fn (mut c hono.Context) http.Response {
return c.text('')
})
```
### 动态路由
支持路径参数和通配符:
```v
// 单参数
app.get('/users/:id', fn (mut c hono.Context) http.Response {
user_id := c.params['id']
return c.json('{"id": "${user_id}"}')
})
// 多参数
app.get('/posts/:id/comments/:comment_id', fn (mut c hono.Context) http.Response {
post_id := c.params['id']
comment_id := c.params['comment_id']
return c.json('{"post_id": "${post_id}", "comment_id": "${comment_id}"}')
})
// 嵌套参数
app.get('/api/users/:user_id/posts/:post_id', fn (mut c hono.Context) http.Response {
user_id := c.params['user_id']
post_id := c.params['post_id']
return c.json('{"user_id": "${user_id}", "post_id": "${post_id}"}')
})
// 通配符
app.get('/files/*', fn (mut c hono.Context) http.Response {
file_path := c.params['*']
return c.text('File: ${file_path}')
})
// 多级通配符
app.get('/api/**/search', fn (mut c hono.Context) http.Response {
return c.json('{"search": "wildcard"}')
})
```
### 响应方法
所有响应方法直接返回 `http.Response`:
```v
// JSON 响应
return c.json('{"message": "Hello"}')
// 文本响应
return c.text('Hello World')
// HTML 响应
return c.html('<h1>Hello</h1>')
// 设置状态码
c.status(404)
return c.json('{"error": "Not Found"}')
```
### 中间件
支持洋葱模型中间件:
```v
// 日志中间件
app.use(fn (mut c hono.Context, next fn (mut hono.Context) http.Response) http.Response {
println('[${time.now()}] ${c.req.method} ${c.url}')
return next(mut c)
})
// 认证中间件
app.use(fn (mut c hono.Context, next fn (mut hono.Context) http.Response) http.Response {
token := c.query['token']
if token == '' {
c.status(401)
return c.json('{"error": "Unauthorized"}')
}
return next(mut c)
})
// 性能监控中间件
app.use(fn (mut c hono.Context, next fn (mut hono.Context) http.Response) http.Response {
start := time.now()
response := next(mut c)
duration := time.now() - start
println('请求处理时间: ${duration.milliseconds()}ms')
return response
})
```
### 静态文件服务
提供类似 Hono.js 的 `serveStatic` 中间件:
```v
// 使用默认配置(./public 目录)
app.use(hono.serve_static_default())
// 指定根目录
app.use(hono.serve_static_root('./static'))
// 指定路径前缀和根目录
app.use(hono.serve_static_path('/assets', './static'))
// 使用自定义配置
options := hono.StaticOptions{
root: './public'
path: '/static'
index: 'index.html'
dotfiles: false
etag: true
last_modified: true
max_age: 3600 // 1小时缓存
headers: {
'X-Custom-Header': 'value'
}
}
app.use(hono.serve_static(options))
```
**特性:**
- 🛡️ 路径遍历攻击防护
- 📁 自动索引文件支持(index.html)
- 🔒 点文件访问控制
- 🏷️ ETag 和 Last-Modified 支持
- 💾 可配置缓存策略
- 📋 自定义响应头
- 🎯 智能 Content-Type 检测
### 查询参数和请求体
```v
// 获取查询参数
app.get('/search', fn (mut c hono.Context) http.Response {
query := c.query['q']
page := c.query['page']
return c.json('{"query": "${query}", "page": "${page}"}')
})
// 获取请求体
app.post('/api/data', fn (mut c hono.Context) http.Response {
println('请求体: ${c.body}')
return c.json('{"received": "${c.body}"}')
})
```
### 路由统计和缓存
```v
// 获取路由统计信息
static_count, dynamic_count, cache_size, cache_capacity := app.get_router_stats()
println('静态路由: ${static_count}, 动态路由: ${dynamic_count}')
println('缓存: ${cache_size}/${cache_capacity}')
// 清理缓存
app.clear_cache()
```
## 示例
### 基础示例
运行完整示例:
```bash
v run example.v
```
示例包含:
- 静态路由
- 动态路由(单参数、多参数、嵌套参数)
- 所有 HTTP 方法
- 中间件功能
- 参数提取和查询参数处理
### 静态文件服务示例
运行静态文件服务示例:
```bash
v run static_example.v
```
这个示例演示了:
- 多个静态文件目录配置
- 自定义缓存策略
- 安全特性演示
- 完整的HTML界面
**重要提示**: 静态文件路径映射
- `./public` 目录 → 访问路径 `/`
- `./static` 目录 → 访问路径 `/assets`
- `./uploads` 目录 → 访问路径 `/files`
例如:
- `./public/test.txt` → `http://localhost:8080/test.txt`
- `./static/style.css` → `http://localhost:8080/assets/style.css`
- `./uploads/sample.json` → `http://localhost:8080/files/sample.json`
### 快速测试
运行简单的静态文件测试:
```bash
v run test_static.v
```
测试文件结构:
```
v-hono/
├── public/
│ ├── index.html # 默认索引文件
│ └── test.txt # 测试文本文件
├── static/
│ ├── style.css # 样式文件
│ └── app.js # JavaScript文件
└── uploads/
└── sample.json # JSON文件
```
## 性能特性
- **混合路由算法**:静态路由 O(1) 查找,动态路由正则匹配
- **LRU 缓存**:自动缓存路由匹配结果
- **Trie 路由树**:支持复杂路径匹配
- **内存优化**:使用指针和堆分配优化性能
## 贡献
欢迎提交 Issue 和 Pull Request!
## 许可证
MIT License