diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..4ed3609
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,58 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+### Added
+- **Group SetNotFoundHandle** - Support custom 404 handler for router groups (#229)
+ - Added `SetNotFoundHandle(handler StandardHandle)` method to Group interface
+ - Group-level 404 handler takes priority over app-level handler
+ - Example: `apiGroup.SetNotFoundHandle(func(ctx Context) error { ... })`
+
+- **Trailing Slash Redirect Configuration** - Control trailing slash redirect behavior (#245)
+ - Added `EnabledRedirectTrailingSlash` configuration option
+ - Default is `false` to match net/http behavior
+ - Set to `true` to enable automatic 301 redirect for trailing slashes
+
+- **CORS Preflight Support** - Fixed CORS preflight request handling (#250)
+ - Modified `DefaultAutoOPTIONSHandler` to include CORS headers
+ - Better integration with CORS middleware
+
+### Fixed
+- **Security Vulnerabilities** - Upgraded dependencies to fix security issues
+ - Upgraded `gopkg.in/yaml.v2` to `v3.0.1` (fixes DoS vulnerability)
+ - Upgraded `golang.org/x/net` to `v0.33.0` (fixes XSS and proxy bypass)
+
+### Changed
+- **Go Version** - Maintained Go 1.21 compatibility
+- **Code Quality** - Improved error handling and nil checks
+
+## [1.0.0] - Previous Release
+
+### Features
+- Support for go mod
+- Static routing, parameter routing, group routing
+- Route support for file/directory services
+- HttpModule support
+- Middleware support (App, Group, Router levels)
+- STRING/JSON/JSONP/HTML output formats
+- Built-in Mock capability
+- Custom Context support
+- Timeout Hook integration
+- Global HTTP error handling
+- Global logging
+- Hijack and WebSocket support
+- Built-in Cache support
+- Built-in Session support with Redis failover
+- Built-in TLS support
+- Third-party template engine support
+- Modular configuration
+- Built-in statistics
+
+---
+
+For more details, see [GitHub Releases](https://github.com/devfeel/dotweb/releases).
diff --git a/README.md b/README.md
index 50423a5..0846f32 100644
--- a/README.md
+++ b/README.md
@@ -175,6 +175,28 @@ test:
curl http://127.0.0.1/user
curl http://127.0.0.1/user/profile
+#### 5) group SetNotFoundHandle (Since v1.8)
+支持为路由组设置独立的 404 处理器,优先于应用级别的 NotFoundHandler。
+``` go
+ // Create API group
+ apiGroup := server.Group("/api")
+
+ // Set group-level 404 handler
+ apiGroup.SetNotFoundHandle(func(ctx dotweb.Context) error {
+ ctx.Response().Header().Set("Content-Type", "application/json")
+ return ctx.WriteString(`{"code": 404, "message": "API resource not found"}`)
+ })
+
+ // Register routes
+ apiGroup.GET("/users", func(ctx dotweb.Context) error {
+ return ctx.WriteString("Users list")
+ })
+```
+Behavior:
+
Request to `/api/users` → Returns "Users list"
+
Request to `/api/unknown` → Returns JSON 404 response (group handler)
+
Request to `/unknown` → Returns global 404 (app handler)
+
## 6. Binder
* HttpContext.Bind(interface{})
diff --git a/group.go b/group.go
index 2e8f516..e144445 100644
--- a/group.go
+++ b/group.go
@@ -2,27 +2,59 @@ package dotweb
import "reflect"
-type (
- Group interface {
- Use(m ...Middleware) Group
- Group(prefix string, m ...Middleware) Group
- DELETE(path string, h HttpHandle) RouterNode
- GET(path string, h HttpHandle) RouterNode
- HEAD(path string, h HttpHandle) RouterNode
- OPTIONS(path string, h HttpHandle) RouterNode
- PATCH(path string, h HttpHandle) RouterNode
- POST(path string, h HttpHandle) RouterNode
- PUT(path string, h HttpHandle) RouterNode
- ServerFile(path string, fileroot string) RouterNode
- RegisterRoute(method, path string, h HttpHandle) RouterNode
- }
- xGroup struct {
- prefix string
- middlewares []Middleware
- allRouterExpress map[string]struct{}
- server *HttpServer
- }
-)
+// Group is the interface that wraps the group router methods.
+// A Group allows you to create routes with a common prefix and middleware chain.
+type Group interface {
+ // Use registers middleware(s) to the group.
+ // Middleware is applied to all routes in this group.
+ Use(m ...Middleware) Group
+
+ // Group creates a new sub-group with the given prefix and optional middleware.
+ // The sub-group inherits middleware from the parent group.
+ Group(prefix string, m ...Middleware) Group
+
+ // DELETE registers a new DELETE route with the given path and handler.
+ DELETE(path string, h HttpHandle) RouterNode
+
+ // GET registers a new GET route with the given path and handler.
+ GET(path string, h HttpHandle) RouterNode
+
+ // HEAD registers a new HEAD route with the given path and handler.
+ HEAD(path string, h HttpHandle) RouterNode
+
+ // OPTIONS registers a new OPTIONS route with the given path and handler.
+ OPTIONS(path string, h HttpHandle) RouterNode
+
+ // PATCH registers a new PATCH route with the given path and handler.
+ PATCH(path string, h HttpHandle) RouterNode
+
+ // POST registers a new POST route with the given path and handler.
+ POST(path string, h HttpHandle) RouterNode
+
+ // PUT registers a new PUT route with the given path and handler.
+ PUT(path string, h HttpHandle) RouterNode
+
+ // ServerFile registers a file server route with the given path and file root.
+ ServerFile(path string, fileroot string) RouterNode
+
+ // RegisterRoute registers a new route with the given HTTP method, path and handler.
+ RegisterRoute(method, path string, h HttpHandle) RouterNode
+
+ // SetNotFoundHandle sets a custom 404 handler for this group.
+ // This handler takes priority over the app-level NotFoundHandler.
+ // If a request path starts with the group's prefix but no route matches,
+ // this handler will be called instead of the global NotFoundHandler.
+ SetNotFoundHandle(handler StandardHandle) Group
+}
+
+// xGroup is the implementation of Group interface.
+type xGroup struct {
+ prefix string
+ middlewares []Middleware
+ allRouterExpress map[string]struct{}
+ server *HttpServer
+ notFoundHandler StandardHandle
+}
func NewGroup(prefix string, server *HttpServer) Group {
g := &xGroup{prefix: prefix, server: server, allRouterExpress: make(map[string]struct{})}
@@ -119,3 +151,12 @@ func (g *xGroup) add(method, path string, handler HttpHandle) RouterNode {
node.Node().groupMiddlewares = g.middlewares
return node
}
+
+// SetNotFoundHandle sets a custom 404 handler for this group.
+// This handler takes priority over the app-level NotFoundHandler.
+// If a request path starts with the group's prefix but no route matches,
+// this handler will be called instead of the global NotFoundHandler.
+func (g *xGroup) SetNotFoundHandle(handler StandardHandle) Group {
+ g.notFoundHandler = handler
+ return g
+}