# 自动解析和自动编码实现方案 ## 核心需求 1. **自动解析**:服务端接收到数据后,自动解析为header和struct,Handler直接使用 2. **自动编码**:Handler返回数据后,自动编码并发送 ## 实现方案 ### 1. 路由配置指定类型 在注册路由时指定请求和响应的类型: ```go // 定义请求和响应类型 type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } type LoginResponse struct { Code int `json:"code"` Token string `json:"token"` } // 注册路由时指定类型 router.RegisterString( "login", loginHandler, router.WithRequestType(&LoginRequest{}), router.WithResponseType(&LoginResponse{}), // 可选 ) ``` ### 2. 服务器自动解析 在服务器接收到数据后,自动进行解析: ```go // 服务器接收到数据 func (h *eventHandler) OnTraffic(c gnet.Conn) { // 1. 读取原始数据 rawData, _ := c.Peek(-1) // 2. 创建Context(包含Request和Response) ctx := h.createContext(c, rawData) // 3. 路由匹配(会返回路由配置,包含请求类型) route, handler := h.router.Match(rawData, ctx) if route == nil { return } // 4. 自动解析请求数据 if route.RequestType() != nil { h.parseRequest(ctx, rawData, route) } // 5. 执行Handler(Handler中可以直接使用解析后的数据) handler(ctx) // 6. 自动发送响应(Response.Write()会自动编码) ctx.Response().Send() } ``` ### 3. 自动解析逻辑 ```go func (h *eventHandler) parseRequest(ctx Context, rawData []byte, route Route) { req := ctx.Request() protocol := req.Protocol() codec := h.getCodec(route) // 1. 协议解码(提取帧头和数据) header, bodyBytes, err := protocol.Decode(rawData) if err != nil { // 处理错误 return } req.SetHeader(header) req.SetDataBytes(bodyBytes) // 2. 数据解码(将字节解码为结构体) if route.RequestType() != nil { body := reflect.New(route.RequestType().Elem()).Interface() if err := codec.Decode(bodyBytes, body); err != nil { // 处理错误 return } req.SetData(body) } } ``` ### 4. 自动编码逻辑 ```go func (resp *responseImpl) Write(data interface{}) error { codec := resp.codec protocol := resp.protocol // 1. 编解码器编码(Go对象 → 字节) bodyBytes, err := codec.Encode(data) if err != nil { return err } // 2. 协议编码(添加帧头) header := resp.Header() frameData, err := protocol.Encode(bodyBytes, header) if err != nil { return err } // 3. 写入连接 return resp.conn.Write(frameData) } ``` ## Handler使用示例 ### 有帧头协议 ```go type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } type LoginResponse struct { Code int `json:"code"` Token string `json:"token"` } // 注册路由 router.RegisterString( "login", loginHandler, router.WithRequestType(&LoginRequest{}), ) // Handler实现(数据已自动解析) func loginHandler(ctx Context) error { req := ctx.Request() resp := ctx.Response() // 直接使用解析后的数据 loginReq := req.Data().(*LoginRequest) username := loginReq.Username password := loginReq.Password // 读取协议帧头(如果有) header := req.Header() if header != nil { messageType := header.Get("message_type") // 使用帧头信息 } // 处理业务逻辑 token := authenticate(username, password) // 设置响应帧头(如果有) respHeader := resp.Header() if respHeader != nil { respHeader.Set("message_type", 0x02) respHeader.Set("status", 0) } // 写入响应(自动编码) return resp.Write(LoginResponse{ Code: 200, Token: token, }) } ``` ### 无帧头协议 ```go type EchoRequest struct { Message string `json:"message"` } type EchoResponse struct { Message string `json:"message"` } // 注册路由 router.RegisterString( "echo", echoHandler, router.WithRequestType(&EchoRequest{}), ) // Handler实现 func echoHandler(ctx Context) error { req := ctx.Request() resp := ctx.Response() // 直接使用解析后的数据(无帧头协议,header为nil) echoReq := req.Data().(*EchoRequest) // 写入响应(自动编码,协议会自动添加\n等分隔符) return resp.Write(EchoResponse{ Message: echoReq.Message, }) } ``` ## 路由接口更新 ```go // RouteOption 路由选项 type RouteOption func(*routeConfig) // WithRequestType 指定请求类型 func WithRequestType(typ interface{}) RouteOption { return func(cfg *routeConfig) { cfg.requestType = reflect.TypeOf(typ) } } // WithResponseType 指定响应类型(可选,主要用于验证) func WithResponseType(typ interface{}) RouteOption { return func(cfg *routeConfig) { cfg.responseType = reflect.TypeOf(typ) } } // Router接口更新 type Router interface { // Register 注册路由(支持选项) Register(matcher Matcher, handler Handler, opts ...RouteOption) Route // RegisterString 注册字符串路由(支持选项) RegisterString(pattern string, handler Handler, opts ...RouteOption) Route // ... 其他方法 } ``` ## 数据流程 ### 读数据(自动解析) ``` 1. 数据到达 → Connection.Read() ↓ 2. 创建Context和Request/Response ↓ 3. 路由匹配 → 找到对应的路由和请求类型 ↓ 4. 协议解码 → Protocol.Decode() → Header + DataBytes ↓ 5. 数据解码 → Codec.Decode() → Go Struct ↓ 6. 设置到Request → Request.SetData(struct) ↓ 7. Handler执行 → 直接使用req.Data().(*MyStruct) ``` ### 写数据(自动编码) ``` 1. Handler调用 → resp.Write(struct) ↓ 2. 编解码器编码 → Codec.Encode() → []byte ↓ 3. 协议编码 → Protocol.Encode() → Header + Data ↓ 4. 写入连接 → Connection.Write() ``` ## 实现步骤 1. ✅ 更新Request和Response接口 2. ⏳ 更新路由接口,支持指定请求/响应类型 3. ⏳ 实现自动解析逻辑 4. ⏳ 实现自动编码逻辑 5. ⏳ 更新服务器代码 6. ⏳ 更新协议实现 7. ⏳ 编写测试用例 ## 优势 1. **自动化**:数据自动解析,无需手动调用Decode 2. **类型安全**:使用强类型,编译时检查 3. **简洁**:Handler代码简洁,直接使用结构体 4. **灵活**:支持有帧头和无帧头协议 5. **可配置**:通过路由配置指定类型