f039f24af167b55d4e8c370dd40efc689a99c0b6
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 检测
安装
# 克隆仓库
git clone https://github.com/your-username/v-hono.git
cd v-hono
# 运行示例
v run example.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 是请求的核心对象,包含所有请求和响应信息:
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 // 响应体
}
构造函数
所有对象都使用构造函数风格创建:
// 创建 Context
ctx := hono.Context.new(req, params, query, body)
// 创建路由器
router := hono.ContextHybridRouter.new()
trie_router := hono.ContextTrieRouter.new()
// 创建缓存
cache := hono.ContextLRUCache.new(1000)
路由方法
支持所有 HTTP 方法:
// 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('')
})
动态路由
支持路径参数和通配符:
// 单参数
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:
// 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"}')
中间件
支持洋葱模型中间件:
// 日志中间件
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 中间件:
// 使用默认配置(./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 检测
查询参数和请求体
// 获取查询参数
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}"}')
})
路由统计和缓存
// 获取路由统计信息
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()
示例
基础示例
运行完整示例:
v run example.v
示例包含:
- 静态路由
- 动态路由(单参数、多参数、嵌套参数)
- 所有 HTTP 方法
- 中间件功能
- 参数提取和查询参数处理
静态文件服务示例
运行静态文件服务示例:
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
快速测试
运行简单的静态文件测试:
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
Languages
V
84.1%
C
10%
HTML
3.6%
Go
1.9%
Shell
0.2%