migr: migration json to x.json2
This commit is contained in:
@@ -3,7 +3,7 @@ module hono
|
|||||||
import crypto.sha256
|
import crypto.sha256
|
||||||
import crypto.rand
|
import crypto.rand
|
||||||
import time
|
import time
|
||||||
import json
|
import x.json2
|
||||||
|
|
||||||
// 用户角色枚举
|
// 用户角色枚举
|
||||||
pub enum UserRole {
|
pub enum UserRole {
|
||||||
@@ -242,7 +242,7 @@ pub fn (mut auth AuthManager) logout(token string) ! {
|
|||||||
// 创建菜单项
|
// 创建菜单项
|
||||||
pub fn (mut auth AuthManager) create_menu_item(name string, path string, icon string, parent_id int, sort_order int, permissions []string) !MenuItem {
|
pub fn (mut auth AuthManager) create_menu_item(name string, path string, icon string, parent_id int, sort_order int, permissions []string) !MenuItem {
|
||||||
now := int(time.now().unix())
|
now := int(time.now().unix())
|
||||||
permissions_json := json.encode(permissions)
|
permissions_json := json2.encode[[]string](permissions)
|
||||||
permissions_sql := permissions_json.replace('"', "''")
|
permissions_sql := permissions_json.replace('"', "''")
|
||||||
|
|
||||||
auth.db.db.exec('INSERT INTO menu_items (name, path, icon, parent_id, sort_order, permissions, status, created_at, updated_at) VALUES ("$name", "$path", "$icon", $parent_id, $sort_order, "$permissions_sql", 1, $now, $now)')
|
auth.db.db.exec('INSERT INTO menu_items (name, path, icon, parent_id, sort_order, permissions, status, created_at, updated_at) VALUES ("$name", "$path", "$icon", $parent_id, $sort_order, "$permissions_sql", 1, $now, $now)')
|
||||||
@@ -280,7 +280,7 @@ pub fn (auth AuthManager) get_all_menu_items() ![]MenuItem {
|
|||||||
mut menus := []MenuItem{}
|
mut menus := []MenuItem{}
|
||||||
for row in rows {
|
for row in rows {
|
||||||
permissions_str := row.vals[6]
|
permissions_str := row.vals[6]
|
||||||
permissions := json.decode([]string, permissions_str) or { []string{} }
|
permissions := json2.decode[[]string](permissions_str) or { []string{} }
|
||||||
|
|
||||||
menus << MenuItem{
|
menus << MenuItem{
|
||||||
id: row.vals[0].int()
|
id: row.vals[0].int()
|
||||||
@@ -327,7 +327,7 @@ pub fn (auth AuthManager) get_user_menus(user User) ![]MenuItem {
|
|||||||
mut menus := []MenuItem{}
|
mut menus := []MenuItem{}
|
||||||
for row in rows {
|
for row in rows {
|
||||||
permissions_str := row.vals[6]
|
permissions_str := row.vals[6]
|
||||||
permissions := json.decode([]string, permissions_str) or { []string{} }
|
permissions := json2.decode[[]string](permissions_str) or { []string{} }
|
||||||
|
|
||||||
menus << MenuItem{
|
menus << MenuItem{
|
||||||
id: row.vals[0].int()
|
id: row.vals[0].int()
|
||||||
|
|||||||
+110
-66
@@ -1,6 +1,6 @@
|
|||||||
module hono
|
module hono
|
||||||
|
|
||||||
import json
|
import x.json2
|
||||||
import net.http
|
import net.http
|
||||||
|
|
||||||
// 登录请求结构
|
// 登录请求结构
|
||||||
@@ -30,20 +30,64 @@ pub:
|
|||||||
permissions []string
|
permissions []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 响应结构体
|
||||||
|
struct ErrorResponseBody {
|
||||||
|
error string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LoginResponseBody {
|
||||||
|
token string
|
||||||
|
expires_at string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RegisterResponseBody {
|
||||||
|
user_id string
|
||||||
|
username string
|
||||||
|
email string
|
||||||
|
role string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MessageResponseBody {
|
||||||
|
message string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProfileResponseBody {
|
||||||
|
user_id string
|
||||||
|
username string
|
||||||
|
email string
|
||||||
|
role string
|
||||||
|
active string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MenusResponseBody {
|
||||||
|
menus []MenuItem
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MenuCreateResponseBody {
|
||||||
|
menu_id string
|
||||||
|
name string
|
||||||
|
path string
|
||||||
|
icon string
|
||||||
|
parent_id string
|
||||||
|
sort_order string
|
||||||
|
permissions string
|
||||||
|
active string
|
||||||
|
}
|
||||||
|
|
||||||
// 认证中间件(只做校验,不注入 user)
|
// 认证中间件(只做校验,不注入 user)
|
||||||
pub fn auth_middleware(auth_manager AuthManager) ContextMiddleware {
|
pub fn auth_middleware(auth_manager AuthManager) ContextMiddleware {
|
||||||
return fn [auth_manager] (mut c Context, next fn (mut Context) http.Response) http.Response {
|
return fn [auth_manager] (mut c Context, next fn (mut Context) http.Response) http.Response {
|
||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
if token == '' {
|
if token == '' {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Authorization token required'
|
error: 'Authorization token required'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ := auth_manager.verify_token(token) or {
|
_ := auth_manager.verify_token(token) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid or expired token'
|
error: 'Invalid or expired token'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return next(mut c)
|
return next(mut c)
|
||||||
@@ -56,14 +100,14 @@ pub fn permission_middleware(auth_manager AuthManager, required_permission strin
|
|||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
user := auth_manager.verify_token(token) or {
|
user := auth_manager.verify_token(token) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid or expired token'
|
error: 'Invalid or expired token'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
if !auth_manager.check_permission(user, required_permission) {
|
if !auth_manager.check_permission(user, required_permission) {
|
||||||
c.status(403)
|
c.status(403)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Insufficient permissions'
|
error: 'Insufficient permissions'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return next(mut c)
|
return next(mut c)
|
||||||
@@ -75,31 +119,31 @@ pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
|
|||||||
// 登录路由
|
// 登录路由
|
||||||
app.post('/api/auth/login', fn [mut auth_manager] (mut c Context) http.Response {
|
app.post('/api/auth/login', fn [mut auth_manager] (mut c Context) http.Response {
|
||||||
body := c.body
|
body := c.body
|
||||||
login_req := json.decode(LoginRequest, body) or {
|
login_req := json2.decode[LoginRequest](body) or {
|
||||||
c.status(400)
|
c.status(400)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid request body'
|
error: 'Invalid request body'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
session := auth_manager.login(login_req.username, login_req.password) or {
|
session := auth_manager.login(login_req.username, login_req.password) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': err.msg()
|
error: err.msg()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[LoginResponseBody](LoginResponseBody{
|
||||||
'token': session.token.str()
|
token: session.token.str()
|
||||||
'expires_at': session.expires_at.str()
|
expires_at: session.expires_at.str()
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
// 注册路由
|
// 注册路由
|
||||||
app.post('/api/auth/register', fn [mut auth_manager] (mut c Context) http.Response {
|
app.post('/api/auth/register', fn [mut auth_manager] (mut c Context) http.Response {
|
||||||
body := c.body
|
body := c.body
|
||||||
register_req := json.decode(RegisterRequest, body) or {
|
register_req := json2.decode[RegisterRequest](body) or {
|
||||||
c.status(400)
|
c.status(400)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid request body'
|
error: 'Invalid request body'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
role := match register_req.role {
|
role := match register_req.role {
|
||||||
@@ -111,15 +155,15 @@ pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
|
|||||||
}
|
}
|
||||||
user := auth_manager.create_user(register_req.username, register_req.email, register_req.password, role) or {
|
user := auth_manager.create_user(register_req.username, register_req.email, register_req.password, role) or {
|
||||||
c.status(400)
|
c.status(400)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': err.msg()
|
error: err.msg()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[RegisterResponseBody](RegisterResponseBody{
|
||||||
'user_id': user.id.str()
|
user_id: user.id.str()
|
||||||
'username': user.username
|
username: user.username
|
||||||
'email': user.email
|
email: user.email
|
||||||
'role': user.role.str()
|
role: user.role.str()
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -128,18 +172,18 @@ pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
|
|||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
if token == '' {
|
if token == '' {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Authorization token required'
|
error: 'Authorization token required'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
auth_manager.logout(token) or {
|
auth_manager.logout(token) or {
|
||||||
c.status(500)
|
c.status(500)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': err.msg()
|
error: err.msg()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[MessageResponseBody](MessageResponseBody{
|
||||||
'message': 'Logged out successfully'
|
message: 'Logged out successfully'
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -148,16 +192,16 @@ pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
|
|||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
user := auth_manager.verify_token(token) or {
|
user := auth_manager.verify_token(token) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid or expired token'
|
error: 'Invalid or expired token'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ProfileResponseBody](ProfileResponseBody{
|
||||||
'user_id': user.id.str()
|
user_id: user.id.str()
|
||||||
'username': user.username
|
username: user.username
|
||||||
'email': user.email
|
email: user.email
|
||||||
'role': user.role.str()
|
role: user.role.str()
|
||||||
'active': user.status.str()
|
active: user.status.str()
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -166,45 +210,45 @@ pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
|
|||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
user := auth_manager.verify_token(token) or {
|
user := auth_manager.verify_token(token) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid or expired token'
|
error: 'Invalid or expired token'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
menus := auth_manager.get_user_menus(user) or {
|
menus := auth_manager.get_user_menus(user) or {
|
||||||
c.status(500)
|
c.status(500)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': err.msg()
|
error: err.msg()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[MenusResponseBody](MenusResponseBody{
|
||||||
'menus': menus
|
menus: menus
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
// 创建菜单项路由 (需要管理员权限)
|
// 创建菜单项路由 (需要管理员权限)
|
||||||
app.post('/api/auth/menus', fn [mut auth_manager] (mut c Context) http.Response {
|
app.post('/api/auth/menus', fn [mut auth_manager] (mut c Context) http.Response {
|
||||||
body := c.body
|
body := c.body
|
||||||
menu_req := json.decode(MenuCreateRequest, body) or {
|
menu_req := json2.decode[MenuCreateRequest](body) or {
|
||||||
c.status(400)
|
c.status(400)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': 'Invalid request body'
|
error: 'Invalid request body'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
menu := auth_manager.create_menu_item(menu_req.name, menu_req.path, menu_req.icon, menu_req.parent_id, menu_req.sort_order, menu_req.permissions) or {
|
menu := auth_manager.create_menu_item(menu_req.name, menu_req.path, menu_req.icon, menu_req.parent_id, menu_req.sort_order, menu_req.permissions) or {
|
||||||
c.status(400)
|
c.status(400)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': err.msg()
|
error: err.msg()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[MenuCreateResponseBody](MenuCreateResponseBody{
|
||||||
'menu_id': menu.id.str()
|
menu_id: menu.id.str()
|
||||||
'name': menu.name
|
name: menu.name
|
||||||
'path': menu.path
|
path: menu.path
|
||||||
'icon': menu.icon
|
icon: menu.icon
|
||||||
'parent_id': menu.parent_id.str()
|
parent_id: menu.parent_id.str()
|
||||||
'sort_order': menu.sort_order.str()
|
sort_order: menu.sort_order.str()
|
||||||
'permissions': json.encode(menu.permissions)
|
permissions: json2.encode[[]string](menu.permissions)
|
||||||
'active': menu.status.str()
|
active: menu.status.str()
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -212,12 +256,12 @@ pub fn register_auth_routes(mut app Hono, mut auth_manager AuthManager) {
|
|||||||
app.get('/api/auth/menus/all', fn [auth_manager] (mut c Context) http.Response {
|
app.get('/api/auth/menus/all', fn [auth_manager] (mut c Context) http.Response {
|
||||||
menus := auth_manager.get_all_menu_items() or {
|
menus := auth_manager.get_all_menu_items() or {
|
||||||
c.status(500)
|
c.status(500)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponseBody](ErrorResponseBody{
|
||||||
'error': err.msg()
|
error: err.msg()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[MenusResponseBody](MenusResponseBody{
|
||||||
'menus': menus
|
menus: menus
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
module hono
|
module hono
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import x.json2
|
||||||
|
|
||||||
// 服务器配置结构
|
// 服务器配置结构
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
@@ -107,7 +107,7 @@ pub fn load_config(config_path string) !AppConfig {
|
|||||||
return error('无法读取配置文件: ${err}')
|
return error('无法读取配置文件: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
config := json.decode(AppConfig, config_content) or {
|
config := json2.decode[AppConfig](config_content) or {
|
||||||
return error('配置文件格式错误: ${err}')
|
return error('配置文件格式错误: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ pub fn load_config(config_path string) !AppConfig {
|
|||||||
|
|
||||||
// 保存配置到文件
|
// 保存配置到文件
|
||||||
pub fn save_config(config AppConfig, config_path string) ! {
|
pub fn save_config(config AppConfig, config_path string) ! {
|
||||||
config_json := json.encode_pretty(config)
|
config_json := json2.encode[AppConfig](config, prettify: true)
|
||||||
|
|
||||||
// 确保目录存在
|
// 确保目录存在
|
||||||
config_dir := os.dir(config_path)
|
config_dir := os.dir(config_path)
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
module hono
|
module hono
|
||||||
|
|
||||||
import net.http
|
import net.http
|
||||||
import json
|
import x.json2
|
||||||
|
|
||||||
// 错误类型枚举
|
// 错误类型枚举
|
||||||
pub enum ErrorType {
|
pub enum ErrorType {
|
||||||
@@ -51,7 +51,7 @@ pub fn (eh DefaultErrorHandler) handle_error(mut c Context, error_type ErrorType
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.status(int(error_type))
|
c.status(int(error_type))
|
||||||
return c.json(json.encode(error_response))
|
return c.json(json2.encode[ErrorResponse](error_response))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取错误名称
|
// 获取错误名称
|
||||||
|
|||||||
+41
-20
@@ -2,7 +2,28 @@ module main
|
|||||||
|
|
||||||
import hono
|
import hono
|
||||||
import net.http
|
import net.http
|
||||||
import json
|
import x.json2
|
||||||
|
|
||||||
|
// 响应结构体
|
||||||
|
struct ErrorResponse {
|
||||||
|
error string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProtectedUserResponse {
|
||||||
|
message string
|
||||||
|
user_id string
|
||||||
|
username string
|
||||||
|
email string
|
||||||
|
role string
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProtectedAdminResponse {
|
||||||
|
message string
|
||||||
|
user_id string
|
||||||
|
username string
|
||||||
|
email string
|
||||||
|
role string
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// 创建数据库管理器
|
// 创建数据库管理器
|
||||||
@@ -37,16 +58,16 @@ fn main() {
|
|||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
user := auth_manager.verify_token(token) or {
|
user := auth_manager.verify_token(token) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponse](ErrorResponse{
|
||||||
'error': 'User not found'
|
error: 'User not found'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ProtectedUserResponse](ProtectedUserResponse{
|
||||||
'message': 'This is a protected user route',
|
message: 'This is a protected user route'
|
||||||
'user_id': user.id.str(),
|
user_id: user.id.str()
|
||||||
'username': user.username,
|
username: user.username
|
||||||
'email': user.email,
|
email: user.email
|
||||||
'role': user.role.str()
|
role: user.role.str()
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -54,22 +75,22 @@ fn main() {
|
|||||||
token := c.req.header.get_custom('Authorization') or { '' }
|
token := c.req.header.get_custom('Authorization') or { '' }
|
||||||
user := auth_manager.verify_token(token) or {
|
user := auth_manager.verify_token(token) or {
|
||||||
c.status(401)
|
c.status(401)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponse](ErrorResponse{
|
||||||
'error': 'User not found'
|
error: 'User not found'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
if !auth_manager.check_permission(user, 'manage') {
|
if !auth_manager.check_permission(user, 'manage') {
|
||||||
c.status(403)
|
c.status(403)
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ErrorResponse](ErrorResponse{
|
||||||
'error': 'Admin access required'
|
error: 'Admin access required'
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return c.json(json.encode({
|
return c.json(json2.encode[ProtectedAdminResponse](ProtectedAdminResponse{
|
||||||
'message': 'This is a protected admin route',
|
message: 'This is a protected admin route'
|
||||||
'user_id': user.id.str(),
|
user_id: user.id.str()
|
||||||
'username': user.username,
|
username: user.username
|
||||||
'email': user.email,
|
email: user.email
|
||||||
'role': user.role.str()
|
role: user.role.str()
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -142,4 +163,4 @@ fn create_sample_users(mut auth_manager hono.AuthManager) {
|
|||||||
auth_manager.create_user('guest', 'guest@example.com', 'guest123', hono.UserRole.guest) or { return }
|
auth_manager.create_user('guest', 'guest@example.com', 'guest123', hono.UserRole.guest) or { return }
|
||||||
|
|
||||||
println('✅ 示例用户已创建')
|
println('✅ 示例用户已创建')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ fn main() {
|
|||||||
create_test_files()
|
create_test_files()
|
||||||
|
|
||||||
// 创建应用
|
// 创建应用
|
||||||
mut app := hono.Hono.new()
|
mut app := &hono.Hono{}
|
||||||
|
|
||||||
// 测试路由
|
// 测试路由
|
||||||
setup_test_routes(mut app)
|
setup_test_routes(mut app)
|
||||||
|
|
||||||
// 在后台启动服务器
|
// 在后台启动服务器
|
||||||
go app.listen(':8081')
|
spawn app.listen(':8081')
|
||||||
|
|
||||||
// 等待服务器启动
|
// 等待服务器启动
|
||||||
time.sleep(2 * time.second)
|
time.sleep(2 * time.second)
|
||||||
@@ -227,8 +227,8 @@ fn test_smart_selection() {
|
|||||||
if result2.exit_code == 0 {
|
if result2.exit_code == 0 {
|
||||||
// 检查下载的文件大小
|
// 检查下载的文件大小
|
||||||
if os.exists('large_output.txt') {
|
if os.exists('large_output.txt') {
|
||||||
downloaded_size := os.file_size('large_output.txt') or { 0 }
|
downloaded_size := os.file_size('large_output.txt')
|
||||||
original_size := os.file_size('test_large.txt') or { 0 }
|
original_size := os.file_size('test_large.txt')
|
||||||
if downloaded_size == original_size {
|
if downloaded_size == original_size {
|
||||||
println('✅ 智能选择大文件: 成功 (${downloaded_size} bytes)')
|
println('✅ 智能选择大文件: 成功 (${downloaded_size} bytes)')
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module hono
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import json
|
import x.json2
|
||||||
|
|
||||||
// 日志级别枚举
|
// 日志级别枚举
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
@@ -150,7 +150,7 @@ fn (l &Logger) format_text_log(entry LogEntry) string {
|
|||||||
|
|
||||||
// 格式化日志消息(JSON格式)
|
// 格式化日志消息(JSON格式)
|
||||||
fn (l &Logger) format_json_log(entry LogEntry) string {
|
fn (l &Logger) format_json_log(entry LogEntry) string {
|
||||||
return json.encode(entry)
|
return json2.encode[LogEntry](entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入日志到文件
|
// 写入日志到文件
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ fn test_integration(mut stats TestStats) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 验证路由统计
|
// 验证路由统计
|
||||||
static_count, dynamic_count, cache_count, _ := app.get_router_stats()
|
static_count, dynamic_count, _, _ := app.get_router_stats()
|
||||||
|
|
||||||
if static_count + dynamic_count < 2 {
|
if static_count + dynamic_count < 2 {
|
||||||
stats.fail_test('路由添加失败')
|
stats.fail_test('路由添加失败')
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import hono
|
import hono
|
||||||
import time
|
|
||||||
import net.http
|
import net.http
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -200,7 +199,7 @@ fn test_restful_api_patterns() {
|
|||||||
|
|
||||||
mut restful_success := 0
|
mut restful_success := 0
|
||||||
for test in restful_tests {
|
for test in restful_tests {
|
||||||
if match_result := app.fast_router.match_route(test['method'], test['path']) {
|
if _ := app.fast_router.match_route(test['method'], test['path']) {
|
||||||
restful_success++
|
restful_success++
|
||||||
println(' ✅ ${test['method']} ${test['path']} - ${test['description']}')
|
println(' ✅ ${test['method']} ${test['path']} - ${test['description']}')
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ fn test_comprehensive_performance() {
|
|||||||
mut complex_matches := 0
|
mut complex_matches := 0
|
||||||
|
|
||||||
for _ in 0 .. test_iterations {
|
for _ in 0 .. test_iterations {
|
||||||
if match_result := app.fast_router.match_route('GET', test['path']) {
|
if _ := app.fast_router.match_route('GET', test['path']) {
|
||||||
complex_matches++
|
complex_matches++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import hono
|
import hono
|
||||||
import net.http
|
import net.http
|
||||||
import json
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println('=== 统一错误处理系统测试 ===')
|
println('=== 统一错误处理系统测试 ===')
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ fn test_memory_management_integration() {
|
|||||||
// 测试缓存操作
|
// 测试缓存操作
|
||||||
cache.put('test_key', test_data)
|
cache.put('test_key', test_data)
|
||||||
|
|
||||||
if cached := cache.get('test_key') {
|
if _ := cache.get('test_key') {
|
||||||
println(' ✅ 缓存存储和获取正常')
|
println(' ✅ 缓存存储和获取正常')
|
||||||
} else {
|
} else {
|
||||||
println(' ❌ 缓存存储或获取失败')
|
println(' ❌ 缓存存储或获取失败')
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ fn test_backward_compatibility() {
|
|||||||
mut router := hono.FastRouter.new()
|
mut router := hono.FastRouter.new()
|
||||||
|
|
||||||
// 测试原有接口是否保持兼容
|
// 测试原有接口是否保持兼容
|
||||||
compatibility_tests := [
|
_ := [
|
||||||
'add_route() 接口',
|
'add_route() 接口',
|
||||||
'match_route() 接口',
|
'match_route() 接口',
|
||||||
'get_stats() 接口',
|
'get_stats() 接口',
|
||||||
@@ -264,7 +264,7 @@ fn test_new_features() {
|
|||||||
mut router := hono.FastRouter.new_with_cache_size(50)
|
mut router := hono.FastRouter.new_with_cache_size(50)
|
||||||
|
|
||||||
// 新功能清单
|
// 新功能清单
|
||||||
new_features := [
|
_ := [
|
||||||
'LRU 缓存机制',
|
'LRU 缓存机制',
|
||||||
'TTL 过期管理',
|
'TTL 过期管理',
|
||||||
'健康状态检查',
|
'健康状态检查',
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ fn test_large_scale_repeated_matching() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证缓存没有增长(说明使用了缓存)
|
// 验证缓存没有增长(说明使用了缓存)
|
||||||
regex_total_after, regex_compiled_after := router.get_regex_cache_stats()
|
_, regex_compiled_after := router.get_regex_cache_stats()
|
||||||
if regex_compiled_after == regex_compiled {
|
if regex_compiled_after == regex_compiled {
|
||||||
println(' ✅ 缓存使用正常 - 没有额外的编译')
|
println(' ✅ 缓存使用正常 - 没有额外的编译')
|
||||||
} else {
|
} else {
|
||||||
@@ -178,7 +178,7 @@ fn test_multi_route_cache_effect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证缓存状态
|
// 验证缓存状态
|
||||||
regex_total_final, regex_compiled_final := router.get_regex_cache_stats()
|
_, regex_compiled_final := router.get_regex_cache_stats()
|
||||||
if regex_compiled_final == regex_compiled_after_first {
|
if regex_compiled_final == regex_compiled_after_first {
|
||||||
println(' ✅ 缓存工作正常 - 没有额外编译')
|
println(' ✅ 缓存工作正常 - 没有额外编译')
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ fn test_cache_hit_rate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 最终缓存状态
|
// 最终缓存状态
|
||||||
regex_total_final, regex_compiled_final := router.get_regex_cache_stats()
|
_, regex_compiled_final := router.get_regex_cache_stats()
|
||||||
|
|
||||||
if regex_compiled_final == regex_compiled_after_first {
|
if regex_compiled_final == regex_compiled_after_first {
|
||||||
println(' ✅ 缓存命中率100% - 没有额外的编译')
|
println(' ✅ 缓存命中率100% - 没有额外的编译')
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ fn test_step_by_step_breakdown() {
|
|||||||
|
|
||||||
// 步骤4: 正则表达式缓存检查
|
// 步骤4: 正则表达式缓存检查
|
||||||
start_time4 := time.now()
|
start_time4 := time.now()
|
||||||
cached_regex := router.regex_cache[route_path]
|
_ := router.regex_cache[route_path]
|
||||||
step4_time := time.since(start_time4)
|
step4_time := time.since(start_time4)
|
||||||
println(' 步骤4 - 正则缓存检查: ${step4_time}')
|
println(' 步骤4 - 正则缓存检查: ${step4_time}')
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ fn (router NoCacheRouter) match_route_no_cache(method string, path string) ?hono
|
|||||||
replaced_path = replaced_path.replace('{', r'\{')
|
replaced_path = replaced_path.replace('{', r'\{')
|
||||||
replaced_path = replaced_path.replace('}', r'\}')
|
replaced_path = replaced_path.replace('}', r'\}')
|
||||||
replaced_path = replaced_path.replace('^', r'\^')
|
replaced_path = replaced_path.replace('^', r'\^')
|
||||||
replaced_path = replaced_path.replace('$', r'\$')
|
replaced_path = replaced_path.replace(r'$', r'\$')
|
||||||
replaced_path = replaced_path.replace('|', r'\|')
|
replaced_path = replaced_path.replace('|', r'\|')
|
||||||
|
|
||||||
// 提取参数名并替换为命名捕获组
|
// 提取参数名并替换为命名捕获组
|
||||||
@@ -68,7 +68,7 @@ fn (router NoCacheRouter) match_route_no_cache(method string, path string) ?hono
|
|||||||
return '(?P<${param_name}>[^/]+)'
|
return '(?P<${param_name}>[^/]+)'
|
||||||
})
|
})
|
||||||
|
|
||||||
replaced_path = '^${replaced_path}$'
|
replaced_path = '^${replaced_path}' + r'$'
|
||||||
|
|
||||||
// 每次都重新编译正则表达式(这是性能瓶颈)
|
// 每次都重新编译正则表达式(这是性能瓶颈)
|
||||||
mut reg := regex.regex_opt(replaced_path) or { continue }
|
mut reg := regex.regex_opt(replaced_path) or { continue }
|
||||||
@@ -384,4 +384,4 @@ fn test_cache_hit_rate() {
|
|||||||
|
|
||||||
// 显示性能分析
|
// 显示性能分析
|
||||||
router.analyze_router_performance()
|
router.analyze_router_performance()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ fn test_step_by_step_performance() {
|
|||||||
|
|
||||||
// 步骤3: 第二次匹配(使用缓存)
|
// 步骤3: 第二次匹配(使用缓存)
|
||||||
start_time3 := time.now()
|
start_time3 := time.now()
|
||||||
result2 := router.match_route('GET', test_path)
|
_ = router.match_route('GET', test_path)
|
||||||
second_match_time := time.since(start_time3)
|
second_match_time := time.since(start_time3)
|
||||||
println(' 第二次匹配时间 (使用缓存): ${second_match_time}')
|
println(' 第二次匹配时间 (使用缓存): ${second_match_time}')
|
||||||
|
|
||||||
@@ -58,31 +58,49 @@ fn test_step_by_step_performance() {
|
|||||||
println(' 路由缓存: ${cache_size}/${cache_capacity}')
|
println(' 路由缓存: ${cache_size}/${cache_capacity}')
|
||||||
println(' 正则缓存: ${regex_compiled}/${regex_total}')
|
println(' 正则缓存: ${regex_compiled}/${regex_total}')
|
||||||
|
|
||||||
// 步骤5: 测试纯正则匹配时间
|
// 步骤5: 测试纯正则匹配时间(安全访问)
|
||||||
if cached := router.regex_cache[route_path] {
|
if cached := router.regex_cache[route_path] {
|
||||||
if cached.compiled {
|
if cached.compiled {
|
||||||
start_time4 := time.now()
|
// 先验证正则能匹配
|
||||||
for _ in 0 .. 1000 {
|
if cached.regex.matches_string(test_path) {
|
||||||
cached.regex.matches_string(test_path)
|
start_time4 := time.now()
|
||||||
|
for _ in 0 .. 1000 {
|
||||||
|
cached.regex.matches_string(test_path)
|
||||||
|
}
|
||||||
|
pure_regex_time := time.since(start_time4)
|
||||||
|
avg_regex_time := f64(pure_regex_time.microseconds()) / 1000.0
|
||||||
|
println(' 纯正则匹配平均时间: ${avg_regex_time:.3f}μs')
|
||||||
|
} else {
|
||||||
|
println(' ⚠️ 正则表达式无法匹配测试路径')
|
||||||
}
|
}
|
||||||
pure_regex_time := time.since(start_time4)
|
|
||||||
avg_regex_time := f64(pure_regex_time.microseconds()) / 1000.0
|
|
||||||
println(' 纯正则匹配平均时间: ${avg_regex_time:.3f}μs')
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
println(' ⚠️ 正则缓存中未找到路由')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 步骤6: 测试参数提取时间
|
// 步骤6: 测试参数提取时间(安全访问)
|
||||||
if cached := router.regex_cache[route_path] {
|
if cached := router.regex_cache[route_path] {
|
||||||
if cached.compiled {
|
if cached.compiled && cached.param_names.len > 0 {
|
||||||
start_time5 := time.now()
|
// 先执行一次匹配确保正则状态正确
|
||||||
for _ in 0 .. 1000 {
|
if cached.regex.matches_string(test_path) {
|
||||||
for param_name in cached.param_names {
|
start_time5 := time.now()
|
||||||
cached.regex.get_group_by_name(test_path, param_name)
|
mut extract_count := 0
|
||||||
|
for _ in 0 .. 1000 {
|
||||||
|
// 每次提取前重新匹配
|
||||||
|
if cached.regex.matches_string(test_path) {
|
||||||
|
for param_name in cached.param_names {
|
||||||
|
group := cached.regex.get_group_by_name(test_path, param_name)
|
||||||
|
if group.len > 0 {
|
||||||
|
extract_count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
param_extract_time := time.since(start_time5)
|
||||||
|
avg_param_time := f64(param_extract_time.microseconds()) / 1000.0
|
||||||
|
println(' 参数提取平均时间: ${avg_param_time:.3f}μs')
|
||||||
|
println(' 参数数量: ${cached.param_names.len}')
|
||||||
}
|
}
|
||||||
param_extract_time := time.since(start_time5)
|
|
||||||
avg_param_time := f64(param_extract_time.microseconds()) / 1000.0
|
|
||||||
println(' 参数提取平均时间: ${avg_param_time:.3f}μs')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,4 +220,4 @@ fn test_complexity_performance() {
|
|||||||
for i, path in dynamic_paths {
|
for i, path in dynamic_paths {
|
||||||
println(' ${i+1}. ${path}')
|
println(' ${i+1}. ${path}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ fn test_basic_performance() {
|
|||||||
mut fast_matches := 0
|
mut fast_matches := 0
|
||||||
for _ in 0 .. iterations {
|
for _ in 0 .. iterations {
|
||||||
fast_router.clear_cache()
|
fast_router.clear_cache()
|
||||||
if match_result := fast_router.match_route('GET', test_path) {
|
if _ := fast_router.match_route('GET', test_path) {
|
||||||
fast_matches++
|
fast_matches++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ fn test_basic_performance() {
|
|||||||
for _ in 0 .. iterations {
|
for _ in 0 .. iterations {
|
||||||
hybrid_router.clear_cache()
|
hybrid_router.clear_cache()
|
||||||
hybrid_router.clear_regex_cache()
|
hybrid_router.clear_regex_cache()
|
||||||
if match_result := hybrid_router.match_route('GET', test_path) {
|
if _ := hybrid_router.match_route('GET', test_path) {
|
||||||
hybrid_matches++
|
hybrid_matches++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ fn test_basic_performance() {
|
|||||||
start_time3 := time.now()
|
start_time3 := time.now()
|
||||||
mut fast_cache_matches := 0
|
mut fast_cache_matches := 0
|
||||||
for _ in 0 .. iterations {
|
for _ in 0 .. iterations {
|
||||||
if match_result := fast_router.match_route('GET', test_path) {
|
if _ := fast_router.match_route('GET', test_path) {
|
||||||
fast_cache_matches++
|
fast_cache_matches++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ fn test_basic_performance() {
|
|||||||
start_time4 := time.now()
|
start_time4 := time.now()
|
||||||
mut hybrid_cache_matches := 0
|
mut hybrid_cache_matches := 0
|
||||||
for _ in 0 .. iterations {
|
for _ in 0 .. iterations {
|
||||||
if match_result := hybrid_router.match_route('GET', test_path) {
|
if _ := hybrid_router.match_route('GET', test_path) {
|
||||||
hybrid_cache_matches++
|
hybrid_cache_matches++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import hono
|
|
||||||
import net.http
|
|
||||||
import os
|
|
||||||
import time
|
import time
|
||||||
import strings
|
import strings
|
||||||
|
|
||||||
@@ -32,14 +29,14 @@ fn test_json_building() {
|
|||||||
|
|
||||||
// 方法1: 使用字符串插值(优化后)
|
// 方法1: 使用字符串插值(优化后)
|
||||||
start_time := time.now()
|
start_time := time.now()
|
||||||
for i in 0 .. 10000 {
|
for _ in 0 .. 10000 {
|
||||||
_ := '{"message": "测试", "params": {"action": "${test_data['action']}", "id": "${test_data['id']}"}}'
|
_ := '{"message": "测试", "params": {"action": "${test_data['action']}", "id": "${test_data['id']}"}}'
|
||||||
}
|
}
|
||||||
interpolation_time := time.since(start_time)
|
interpolation_time := time.since(start_time)
|
||||||
|
|
||||||
// 方法2: 使用StringBuilder(复杂场景)
|
// 方法2: 使用StringBuilder(复杂场景)
|
||||||
start_time2 := time.now()
|
start_time2 := time.now()
|
||||||
for i in 0 .. 10000 {
|
for _ in 0 .. 10000 {
|
||||||
mut builder := strings.new_builder(256)
|
mut builder := strings.new_builder(256)
|
||||||
builder.write_string('{"message": "测试", "params": {"action": "')
|
builder.write_string('{"message": "测试", "params": {"action": "')
|
||||||
builder.write_string(test_data['action'])
|
builder.write_string(test_data['action'])
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module hono
|
|||||||
import net.http
|
import net.http
|
||||||
import os
|
import os
|
||||||
import crypto.md5
|
import crypto.md5
|
||||||
import json
|
import x.json2
|
||||||
import time
|
import time
|
||||||
|
|
||||||
// 分片上传配置
|
// 分片上传配置
|
||||||
@@ -291,7 +291,7 @@ pub fn (manager ChunkUploadManager) get_upload_status(mut ctx Context) http.Resp
|
|||||||
return ctx.resource_not_found('upload', file_hash)
|
return ctx.resource_not_found('upload', file_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.json(json.encode(upload_status))
|
return ctx.json(json2.encode[FileUploadStatus](upload_status))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新上传状态
|
// 更新上传状态
|
||||||
|
|||||||
Reference in New Issue
Block a user