|
|
package request
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
|
|
|
protocolpkg "github.com/noahlann/nnet/pkg/protocol"
|
|
|
requestpkg "github.com/noahlann/nnet/pkg/request"
|
|
|
)
|
|
|
|
|
|
// requestImpl 请求实现
|
|
|
// 实现了Request和RequestSetter接口
|
|
|
type requestImpl struct {
|
|
|
raw []byte
|
|
|
data interface{}
|
|
|
dataBytes []byte
|
|
|
header requestpkg.FrameHeader
|
|
|
protocol protocolpkg.Protocol
|
|
|
}
|
|
|
|
|
|
// 确保requestImpl实现了RequestSetter接口
|
|
|
var _ RequestSetter = (*requestImpl)(nil)
|
|
|
|
|
|
// New 创建新的请求对象
|
|
|
func New(raw []byte, protocol protocolpkg.Protocol) requestpkg.Request {
|
|
|
return &requestImpl{
|
|
|
raw: raw,
|
|
|
protocol: protocol,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Raw 获取原始数据
|
|
|
func (r *requestImpl) Raw() []byte {
|
|
|
return r.raw
|
|
|
}
|
|
|
|
|
|
// Data 获取数据部分(已自动解码为Go对象)
|
|
|
func (r *requestImpl) Data() interface{} {
|
|
|
return r.data
|
|
|
}
|
|
|
|
|
|
// SetData 设置数据部分(内部使用,导出以供服务器使用)
|
|
|
func (r *requestImpl) SetData(data interface{}) {
|
|
|
r.data = data
|
|
|
}
|
|
|
|
|
|
// Bind 绑定到指定的结构体
|
|
|
func (r *requestImpl) Bind(v interface{}) error {
|
|
|
// 如果Data已经存在,直接使用Data
|
|
|
if r.data != nil {
|
|
|
// 使用反射将data的值复制到v
|
|
|
// 这里简化处理,实际可以使用json或其他序列化方式
|
|
|
return bindDataToStruct(r.data, v)
|
|
|
}
|
|
|
|
|
|
// 如果Data不存在,但有DataBytes,使用DataBytes进行解码
|
|
|
if len(r.dataBytes) > 0 {
|
|
|
// 这里需要知道使用什么codec,但Request没有codec信息
|
|
|
// 所以Bind方法主要用于将已解码的Data绑定到指定的struct
|
|
|
// 如果需要从DataBytes解码,应该直接使用Data()获取结果
|
|
|
return fmt.Errorf("data bytes available but no codec specified, use Data() method instead")
|
|
|
}
|
|
|
|
|
|
return fmt.Errorf("no data available to bind")
|
|
|
}
|
|
|
|
|
|
// bindDataToStruct 将data绑定到struct
|
|
|
func bindDataToStruct(data interface{}, v interface{}) error {
|
|
|
// 使用JSON作为中间格式进行绑定
|
|
|
// 这适用于大部分场景
|
|
|
dataBytes, err := json.Marshal(data)
|
|
|
if err != nil {
|
|
|
return fmt.Errorf("failed to marshal data: %w", err)
|
|
|
}
|
|
|
|
|
|
return json.Unmarshal(dataBytes, v)
|
|
|
}
|
|
|
|
|
|
// Header 获取协议帧头
|
|
|
func (r *requestImpl) Header() requestpkg.FrameHeader {
|
|
|
return r.header
|
|
|
}
|
|
|
|
|
|
// SetHeader 设置协议帧头(内部使用,导出以供服务器使用)
|
|
|
func (r *requestImpl) SetHeader(header requestpkg.FrameHeader) {
|
|
|
r.header = header
|
|
|
}
|
|
|
|
|
|
// DataBytes 获取数据部分的原始字节
|
|
|
func (r *requestImpl) DataBytes() []byte {
|
|
|
return r.dataBytes
|
|
|
}
|
|
|
|
|
|
// SetDataBytes 设置数据部分的原始字节(内部使用,导出以供服务器使用)
|
|
|
func (r *requestImpl) SetDataBytes(dataBytes []byte) {
|
|
|
r.dataBytes = dataBytes
|
|
|
}
|
|
|
|
|
|
// Protocol 获取协议信息
|
|
|
func (r *requestImpl) Protocol() protocolpkg.Protocol {
|
|
|
return r.protocol
|
|
|
}
|
|
|
|
|
|
// ProtocolVersion 获取协议版本
|
|
|
func (r *requestImpl) ProtocolVersion() string {
|
|
|
if r.protocol != nil {
|
|
|
return r.protocol.Version()
|
|
|
}
|
|
|
return ""
|
|
|
}
|
|
|
|
|
|
// Reset 重置Request状态(用于对象池)
|
|
|
func (r *requestImpl) Reset() {
|
|
|
r.raw = nil
|
|
|
r.data = nil
|
|
|
r.dataBytes = nil
|
|
|
r.header = nil
|
|
|
r.protocol = nil
|
|
|
}
|