# 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.new_hono() // 基本路由 app.get('/', fn (mut c hono.Context) http.Response { return c.html('

Hello V-Hono!

') }) 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('

Hello

') // 设置状态码 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