refl: add hono Context
This commit is contained in:
+94
-83
@@ -3,78 +3,95 @@ module hono
|
||||
import net.urllib
|
||||
import net.http
|
||||
|
||||
struct Router {
|
||||
// Context 路由器
|
||||
struct ContextRouter {
|
||||
mut:
|
||||
handlers struct {
|
||||
mut:
|
||||
get []IRequestHandler
|
||||
post []IRequestHandler
|
||||
put []IRequestHandler
|
||||
delete []IRequestHandler
|
||||
patch []IRequestHandler
|
||||
head []IRequestHandler
|
||||
options []IRequestHandler
|
||||
get []IHandler
|
||||
post []IHandler
|
||||
put []IHandler
|
||||
delete []IHandler
|
||||
patch []IHandler
|
||||
head []IHandler
|
||||
options []IHandler
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Hono {
|
||||
mut:
|
||||
server http.Server = http.Server{}
|
||||
router Router = Router{}
|
||||
routes map[string] Hono = {}
|
||||
base_path string
|
||||
pub mut:
|
||||
hybrid_router HybridRouter
|
||||
trie_router TrieRouter
|
||||
middlewares []Middleware
|
||||
context_router ContextRouter = ContextRouter{}
|
||||
context_hybrid_router ContextHybridRouter
|
||||
context_trie_router ContextTrieRouter
|
||||
context_middlewares []ContextMiddleware
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) get(path string, handler fn (Request) http.Response) {
|
||||
h := RequestHandler{
|
||||
// Context 中间件类型
|
||||
type ContextMiddleware = fn (mut c Context, next fn (mut Context) http.Response) http.Response
|
||||
|
||||
// Context 接口方法
|
||||
pub fn (mut app Hono) get(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{
|
||||
path: path
|
||||
handler: handler
|
||||
}
|
||||
app.hybrid_router.add_route('GET', h, '')
|
||||
app.trie_router.add_route('GET', path, h)
|
||||
app.context_hybrid_router.add_route('GET', h, '')
|
||||
app.context_trie_router.add_route('GET', path, h)
|
||||
app.context_router.handlers.get << h
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) post(path string, handler fn (Request) http.Response) {
|
||||
h := RequestHandler{
|
||||
pub fn (mut app Hono) post(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{
|
||||
path: path
|
||||
handler: handler
|
||||
}
|
||||
app.hybrid_router.add_route('POST', h, '')
|
||||
app.trie_router.add_route('POST', path, h)
|
||||
app.context_hybrid_router.add_route('POST', h, '')
|
||||
app.context_trie_router.add_route('POST', path, h)
|
||||
app.context_router.handlers.post << h
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) put(path string, handler fn (Request) http.Response) {
|
||||
handlers := RequestHandler{path, handler}
|
||||
app.router.handlers.put << handlers
|
||||
app.hybrid_router.add_route('PUT', handlers, app.base_path)
|
||||
pub fn (mut app Hono) put(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{path, handler}
|
||||
app.context_router.handlers.put << h
|
||||
app.context_hybrid_router.add_route('PUT', h, app.base_path)
|
||||
app.context_trie_router.add_route('PUT', path, h)
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) delete(path string, handler fn (Request) http.Response) {
|
||||
handlers := RequestHandler{path, handler}
|
||||
app.router.handlers.delete << handlers
|
||||
app.hybrid_router.add_route('DELETE', handlers, app.base_path)
|
||||
pub fn (mut app Hono) delete(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{path, handler}
|
||||
app.context_router.handlers.delete << h
|
||||
app.context_hybrid_router.add_route('DELETE', h, app.base_path)
|
||||
app.context_trie_router.add_route('DELETE', path, h)
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) patch(path string, handler fn (Request) http.Response) {
|
||||
handlers := RequestHandler{path, handler}
|
||||
app.router.handlers.patch << handlers
|
||||
app.hybrid_router.add_route('PATCH', handlers, app.base_path)
|
||||
pub fn (mut app Hono) patch(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{path, handler}
|
||||
app.context_router.handlers.patch << h
|
||||
app.context_hybrid_router.add_route('PATCH', h, app.base_path)
|
||||
app.context_trie_router.add_route('PATCH', path, h)
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) head(path string, handler fn (Request) http.Response) {
|
||||
handlers := RequestHandler{path, handler}
|
||||
app.router.handlers.head << handlers
|
||||
app.hybrid_router.add_route('HEAD', handlers, app.base_path)
|
||||
pub fn (mut app Hono) head(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{path, handler}
|
||||
app.context_router.handlers.head << h
|
||||
app.context_hybrid_router.add_route('HEAD', h, app.base_path)
|
||||
app.context_trie_router.add_route('HEAD', path, h)
|
||||
}
|
||||
|
||||
pub fn (mut app Hono) options(path string, handler fn (Request) http.Response) {
|
||||
handlers := RequestHandler{path, handler}
|
||||
app.router.handlers.options << handlers
|
||||
app.hybrid_router.add_route('OPTIONS', handlers, app.base_path)
|
||||
pub fn (mut app Hono) options(path string, handler fn (mut Context) http.Response) {
|
||||
h := ContextHandler{path, handler}
|
||||
app.context_router.handlers.options << h
|
||||
app.context_hybrid_router.add_route('OPTIONS', h, app.base_path)
|
||||
app.context_trie_router.add_route('OPTIONS', path, h)
|
||||
}
|
||||
|
||||
// Context 中间件
|
||||
pub fn (mut app Hono) use(mw ContextMiddleware) {
|
||||
app.context_middlewares << mw
|
||||
}
|
||||
|
||||
struct ServerHanler {
|
||||
@@ -88,12 +105,6 @@ fn server_hanler_new(app Hono) ServerHanler {
|
||||
}
|
||||
}
|
||||
|
||||
type Middleware = fn (mut req Request, next fn (mut Request) http.Response) http.Response
|
||||
|
||||
pub fn (mut app Hono) use(mw Middleware) {
|
||||
app.middlewares << mw
|
||||
}
|
||||
|
||||
fn (mut s ServerHanler) handle(req http.Request) http.Response {
|
||||
mut res := http.Response{
|
||||
status_code: 404
|
||||
@@ -104,7 +115,9 @@ fn (mut s ServerHanler) handle(req http.Request) http.Response {
|
||||
path: '/'
|
||||
}
|
||||
}
|
||||
if route_match := s.app.hybrid_router.match_route(req.method.str(), url.path) {
|
||||
|
||||
// 尝试 Context 路由
|
||||
if route_match := s.app.context_hybrid_router.match_route(req.method.str(), url.path) {
|
||||
// 解析 query
|
||||
raw_query := url.query().to_map()
|
||||
mut query_map := map[string]string{}
|
||||
@@ -117,29 +130,25 @@ fn (mut s ServerHanler) handle(req http.Request) http.Response {
|
||||
param_map := route_match.params.clone()
|
||||
// body
|
||||
body := req.data
|
||||
// 构造 hono.Request
|
||||
mut hreq := Request{
|
||||
url: url.path
|
||||
param: param_map
|
||||
query: query_map
|
||||
body: body
|
||||
}
|
||||
// 构造 Context
|
||||
mut ctx := Context.new(req, param_map, query_map, body)
|
||||
// 洋葱模型递归执行中间件
|
||||
return s.exec_middlewares(0, mut hreq, fn [route_match] (req Request) http.Response {
|
||||
return route_match.handler.handle(req)
|
||||
return s.exec_context_middlewares(0, mut ctx, fn [route_match] (mut c Context) http.Response {
|
||||
return route_match.handler.handle(mut c)
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fn (mut s ServerHanler) exec_middlewares(idx int, mut req Request, handler fn (Request) http.Response) http.Response {
|
||||
if idx < s.app.middlewares.len {
|
||||
mw := s.app.middlewares[idx]
|
||||
return mw(mut req, fn [mut s, idx, handler] (mut r Request) http.Response {
|
||||
return s.exec_middlewares(idx+1, mut r, handler)
|
||||
// Context 版本的中间件执行函数
|
||||
fn (mut s ServerHanler) exec_context_middlewares(idx int, mut ctx Context, handler fn (mut Context) http.Response) http.Response {
|
||||
if idx < s.app.context_middlewares.len {
|
||||
mw := s.app.context_middlewares[idx]
|
||||
return mw(mut ctx, fn [mut s, idx, handler] (mut c Context) http.Response {
|
||||
return s.exec_context_middlewares(idx+1, mut c, handler)
|
||||
})
|
||||
} else {
|
||||
return handler(req)
|
||||
return handler(mut ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,27 +162,27 @@ pub fn (mut app Hono) route(prefix string, mut subapp Hono) {
|
||||
// 简化路由合并,直接添加所有处理器
|
||||
app.routes[prefix] = subapp
|
||||
|
||||
// 将子应用的路由添加到主应用
|
||||
for handler in subapp.router.handlers.get {
|
||||
app.router.handlers.get << handler
|
||||
// 合并 Context 路由
|
||||
for handler in subapp.context_router.handlers.get {
|
||||
app.context_router.handlers.get << handler
|
||||
}
|
||||
for handler in subapp.router.handlers.post {
|
||||
app.router.handlers.post << handler
|
||||
for handler in subapp.context_router.handlers.post {
|
||||
app.context_router.handlers.post << handler
|
||||
}
|
||||
for handler in subapp.router.handlers.put {
|
||||
app.router.handlers.put << handler
|
||||
for handler in subapp.context_router.handlers.put {
|
||||
app.context_router.handlers.put << handler
|
||||
}
|
||||
for handler in subapp.router.handlers.delete {
|
||||
app.router.handlers.delete << handler
|
||||
for handler in subapp.context_router.handlers.delete {
|
||||
app.context_router.handlers.delete << handler
|
||||
}
|
||||
for handler in subapp.router.handlers.patch {
|
||||
app.router.handlers.patch << handler
|
||||
for handler in subapp.context_router.handlers.patch {
|
||||
app.context_router.handlers.patch << handler
|
||||
}
|
||||
for handler in subapp.router.handlers.head {
|
||||
app.router.handlers.head << handler
|
||||
for handler in subapp.context_router.handlers.head {
|
||||
app.context_router.handlers.head << handler
|
||||
}
|
||||
for handler in subapp.router.handlers.options {
|
||||
app.router.handlers.options << handler
|
||||
for handler in subapp.context_router.handlers.options {
|
||||
app.context_router.handlers.options << handler
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,23 +190,25 @@ pub fn (mut app Hono) set_base_path(base_path string) {
|
||||
app.base_path = base_path
|
||||
}
|
||||
|
||||
// 路由统计信息
|
||||
pub fn (app Hono) get_router_stats() (int, int, int, int) {
|
||||
static_paths, dynamic_paths := app.hybrid_router.get_all_routes()
|
||||
cache_size, cache_capacity := app.hybrid_router.get_cache_stats()
|
||||
static_paths, dynamic_paths := app.context_hybrid_router.get_all_routes()
|
||||
cache_size, cache_capacity := app.context_hybrid_router.get_cache_stats()
|
||||
return static_paths.len, dynamic_paths.len, cache_size, cache_capacity
|
||||
}
|
||||
|
||||
// 清理缓存
|
||||
pub fn (mut app Hono) clear_cache() {
|
||||
app.hybrid_router.clear_cache()
|
||||
app.context_hybrid_router.clear_cache()
|
||||
}
|
||||
|
||||
pub fn new_hono() Hono {
|
||||
return Hono{
|
||||
server: http.Server{}
|
||||
router: Router{}
|
||||
routes: map[string]Hono{}
|
||||
base_path: ''
|
||||
hybrid_router: new_hybrid_router()
|
||||
trie_router: new_trie_router()
|
||||
context_router: ContextRouter{}
|
||||
context_hybrid_router: ContextHybridRouter.new()
|
||||
context_trie_router: ContextTrieRouter.new()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user