You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Take the IP decoding mentioned in README.md as an example:
typeServiceinterface {
// @kok(op): POST /logs// @kok(param): ip < in:header,name:X-Forwarded-For// @kok(param): ip < in:request,name:RemoteAddrLog(ctx context.Context, ip net.IP) (errerror)
}
// The equivalent annotations.typeServiceinterface {
// @kok(op): POST /logs// @kok(param): ip < in:header,name:X-Forwarded-For// @kok(param): < in:request,name:RemoteAddrLog(ctx context.Context, ip net.IP) (errerror)
}
// You must customize the decoding of `ip` later (conventionally in another file named `codec.go`).// See examples in the `Encoding and decoding` section.// HTTP request:// $ http POST /logs
The existing solution is to implement a new codec:
// codec.goimport (
"fmt""net""strings""github.com/RussellLuo/kok/pkg/codec/httpcodec"
)
typeCodecstruct {
httpcodec.JSON
}
func (cCodec) DecodeRequestParams(namestring, valuesmap[string][]string, outinterface{}) error {
switchname {
case"ip":
// We are decoding the "ip" argument.remote:=values["request.RemoteAddr"][0]
iffwdFor:=values["header.X-Forwarded-For"][0]; fwdFor!="" {
remote=strings.TrimSpace(strings.Split(fwdFor, ",")[0])
}
ipStr, _, err:=net.SplitHostPort(remote)
iferr!=nil {
ipStr=remote// OK; probably didn't have a port
}
ip:=net.ParseIP(ipStr)
ifip==nil {
returnfmt.Errorf("invalid client IP address: %s", ipStr)
}
outIP:=out.(*net.IP)
*outIP=ipreturnnildefault:
// Use the JSON codec for other arguments.returnc.JSON.DecodeRequestParams(name, values, out)
}
}
funcNewCodecs() *httpcodec.DefaultCodecs {
returnhttpcodec.NewDefaultCodecs(Codec{})
}
While the above solution is feasible, the custom encoding and decoding behavior here is so common that we should provide:
an easier way to customize codecs for request parameters
and better code reusability for custom codecs
Proposed Solution
Add support for patching existing codecs, which is shown as below:
// codec.goimport (
"fmt""net""strings""github.com/RussellLuo/kok/pkg/codec/httpcodec"
)
// IPCodec is used to encode and decode an IP. It can be reused wherever needed.typeIPCodecstruct{}
func (cIPCodec) Decode(inmap[string][]string, outinterface{}) error {
remote:=in["request.RemoteAddr"][0]
iffwdFor:=in["header.X-Forwarded-For"][0]; fwdFor!="" {
remote=strings.TrimSpace(strings.Split(fwdFor, ",")[0])
}
ipStr, _, err:=net.SplitHostPort(remote)
iferr!=nil {
ipStr=remote// OK; probably didn't have a port
}
ip:=net.ParseIP(ipStr)
ifip==nil {
returnfmt.Errorf("invalid client IP address: %s", ipStr)
}
outIP:=out.(*net.IP)
*outIP=ipreturnnil
}
func (cIPCodec) Encode(ininterface{}) (outmap[string][]string) {
returnnil
}
funcNewCodecs() *httpcodec.DefaultCodecs {
// Use IPCodec to encode and decode the argument named "ip", if exists,// for the operation named "Log".returnhttpcodec.NewDefaultCodecs(nil,
httpcodec.Op("Log", httpcodec.NewPatcher(httpcodec.JSON{}).Params("ip", IPCodec{})))
}
// Another way to create the codecs.funcNewCodecs2() *httpcodec.DefaultCodecs {
// Use IPCodec to encode and decode the argument named "ip", if exists,// for all the operations.returnhttpcodec.NewDefaultCodecs(nil).
PatchAll(func(c httpcodec.Codec) *httpcodec.Patcher {
returnhttpcodec.NewPatcher(c).Params("ip", IPCodec{})
})
}
The text was updated successfully, but these errors were encountered:
Motivation
Take the
IP decoding
mentioned in README.md as an example:The existing solution is to implement a new codec:
While the above solution is feasible, the custom encoding and decoding behavior here is so common that we should provide:
Proposed Solution
Add support for patching existing codecs, which is shown as below:
The text was updated successfully, but these errors were encountered: