From 5a108290416f4733b1635d73f05cf7db9ca64f11 Mon Sep 17 00:00:00 2001 From: wjqserver <114663932+WJQSERVER@users.noreply.github.com> Date: Wed, 28 May 2025 21:34:08 +0800 Subject: [PATCH 1/3] add ErrorUseHandle --- context.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/context.go b/context.go index 4efb57d..69b5073 100644 --- a/context.go +++ b/context.go @@ -437,3 +437,16 @@ func (c *Context) GetReqHeader(key string) string { func (c *Context) GetAllReqHeader() http.Header { return c.Request.Header } + +// 使用定义的errorHandle来处理error并结束当前handle +func (c *Context) ErrorUseHandle(code int) { + if c.engine != nil && c.engine.errorHandle.handler != nil { + c.engine.errorHandle.handler(c, code) + c.Abort() + return + } else { + // Default error handling if no custom handler is set + c.String(code, http.StatusText(code)) + c.Abort() + } +} From 54ff216eff3067c14a62caf4069d6a9cb93387b9 Mon Sep 17 00:00:00 2001 From: wjqserver <114663932+WJQSERVER@users.noreply.github.com> Date: Thu, 29 May 2025 21:27:35 +0800 Subject: [PATCH 2/3] add static --- engine.go | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/engine.go b/engine.go index 8f5d406..c3e4743 100644 --- a/engine.go +++ b/engine.go @@ -677,3 +677,133 @@ func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) IR engine: group.engine, // 指向 Engine 实例 } } + +// == 其他操作方式 === + +// Static FileServer 传入一个文件夹路径, 使用FileServer进行处理 +func (engine *Engine) Static(relativePath, rootPath string) { + // 清理路径 + relativePath = path.Clean(relativePath) + rootPath = path.Clean(rootPath) + + // 确保相对路径以 '/' 结尾,以便 FileServer 正确处理子路径 + if !strings.HasSuffix(relativePath, "/") { + relativePath += "/" + } + + // 创建一个文件系统处理器 + fileServer := http.FileServer(http.Dir(rootPath)) + + // 注册一个捕获所有路径的路由,使用自定义处理器 + // 注意:这里使用 ANY 方法,但 FileServer 通常只处理 GET 和 HEAD + // 我们可以通过在处理函数内部检查方法来限制 + engine.ANY(relativePath+"*filepath", func(c *Context) { + // 检查是否是 GET 或 HEAD 方法 + if c.Request.Method != http.MethodGet && c.Request.Method != http.MethodHead { + // 如果不是,且启用了 MethodNotAllowed 处理,则继续到 MethodNotAllowed 中间件 + if engine.HandleMethodNotAllowed { + c.Next() + } else { + // 否则,返回 405 Method Not Allowed + engine.errorHandle.handler(c, http.StatusMethodNotAllowed) + } + return + } + + requestPath := c.Request.URL.Path + + // 获取捕获到的文件路径参数 + filepath := c.Param("filepath") + + // 构造文件服务器需要处理的请求路径 + // FileServer 会将请求路径与 http.Dir 的根路径结合 + // 我们需要移除相对路径前缀,只保留文件路径部分 + // 例如,如果 relativePath 是 "/static/",请求是 "/static/js/app.js" + // FileServer 需要的路径是 "/js/app.js" + // 这里的 filepath 参数已经包含了 "/" 前缀,例如 "/js/app.js" + // 所以直接使用 filepath 即可 + c.Request.URL.Path = filepath + + // 使用自定义的 ResponseWriter 包装器来捕获 FileServer 可能返回的错误状态码 + // 这样我们可以在 FileServer 返回 404 或 403 时,使用 Engine 的 ErrorHandler 进行统一处理 + ecw := AcquireErrorCapturingResponseWriter(c, c.engine.errorHandle.handler) + defer ReleaseErrorCapturingResponseWriter(ecw) + + // + // 调用 FileServer 处理请求 + fileServer.ServeHTTP(ecw, c.Request) + + // 在 FileServer 处理完成后,检查是否捕获到错误状态码,并调用 ErrorHandler + ecw.processAfterFileServer() + + // 恢复原始请求路径,以便后续中间件或日志记录使用 + c.Request.URL.Path = requestPath + + // 中止处理链,因为 FileServer 已经处理了响应 + c.Abort() + }) +} + +// Group的Static +func (group *RouterGroup) Static(relativePath, rootPath string) { + // 清理路径 + relativePath = path.Clean(relativePath) + rootPath = path.Clean(rootPath) + + // 确保相对路径以 '/' 结尾,以便 FileServer 正确处理子路径 + if !strings.HasSuffix(relativePath, "/") { + relativePath += "/" + } + + // 创建一个文件系统处理器 + fileServer := http.FileServer(http.Dir(rootPath)) + + // 注册一个捕获所有路径的路由,使用自定义处理器 + // 注意:这里使用 ANY 方法,但 FileServer 通常只处理 GET 和 HEAD + // 我们可以通过在处理函数内部检查方法来限制 + group.ANY(relativePath+"*filepath", func(c *Context) { + // 检查是否是 GET 或 HEAD 方法 + if c.Request.Method != http.MethodGet && c.Request.Method != http.MethodHead { + // 如果不是,且启用了 MethodNotAllowed 处理,则继续到 MethodNotAllowed 中间件 + if group.engine.HandleMethodNotAllowed { + c.Next() + } else { + // 否则,返回 405 Method Not Allowed + group.engine.errorHandle.handler(c, http.StatusMethodNotAllowed) + } + return + } + + requestPath := c.Request.URL.Path + + // 获取捕获到的文件路径参数 + filepath := c.Param("filepath") + + // 构造文件服务器需要处理的请求路径 + // FileServer 会将请求路径与 http.Dir 的根路径结合 + // 我们需要移除相对路径前缀,只保留文件路径部分 + // 例如,如果 relativePath 是 "/static/",请求是 "/static/js/app.js" + // FileServer 需要的路径是 "/js/app.js" + // 这里的 filepath 参数已经包含了 "/" 前缀,例如 "/js/app.js" + // 所以直接使用 filepath 即可 + c.Request.URL.Path = filepath + + // 使用自定义的 ResponseWriter 包装器来捕获 FileServer 可能返回的错误状态码 + // 这样我们可以在 FileServer 返回 404 或 403 时,使用 Engine 的 ErrorHandler 进行统一处理 + ecw := AcquireErrorCapturingResponseWriter(c, group.engine.errorHandle.handler) + defer ReleaseErrorCapturingResponseWriter(ecw) + + // + // 调用 FileServer 处理请求 + fileServer.ServeHTTP(ecw, c.Request) + + // 在 FileServer 处理完成后,检查是否捕获到错误状态码,并调用 ErrorHandler + ecw.processAfterFileServer() + + // 恢复原始请求路径,以便后续中间件或日志记录使用 + c.Request.URL.Path = requestPath + + // 中止处理链,因为 FileServer 已经处理了响应 + c.Abort() + }) +} From 4f0363a62f4a6690946d26811a3d590e55a4e26a Mon Sep 17 00:00:00 2001 From: wjqserver <114663932+WJQSERVER@users.noreply.github.com> Date: Thu, 29 May 2025 21:48:22 +0800 Subject: [PATCH 3/3] fix mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 42be0b7..a798659 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/WJQSERVER/touka +module github.com/infinite-iroha/touka go 1.24.3