Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
07d4085201 | |||
45f30c0be3 | |||
bcaea675a7 | |||
3087ba1d73 |
@@ -17,7 +17,7 @@ syntax = "proto3";
|
||||
package micro.codec;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "github.com/unistack-org/micro/v3/codec;codec";
|
||||
option go_package = "go.unistack.org/micro/v3/codec;codec";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "MicroCodec";
|
||||
option java_package = "micro.codec";
|
||||
|
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4
|
||||
github.com/unistack-org/micro-proto v0.0.9
|
||||
go.unistack.org/micro-proto/v3 v3.1.0
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
)
|
||||
|
10
go.sum
10
go.sum
@@ -1,7 +1,5 @@
|
||||
github.com/ef-ds/deque v1.0.4 h1:iFAZNmveMT9WERAkqLJ+oaABF9AcVQ5AjXem/hroniI=
|
||||
github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
@@ -11,14 +9,10 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34 h1:vBfVmA5mZhsQa2jr1FOL9nfA37N/jnbBmi5XUfviVTI=
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
|
||||
github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4 h1:fOH64AB0C3ixGf9emky61STvPJL3smxJg+1Zwx1oCdg=
|
||||
github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
|
||||
github.com/unistack-org/micro-proto v0.0.9 h1:KrWLS4FUX7UAWNAilQf70uad6ZPf/0EudeddCXllRVc=
|
||||
github.com/unistack-org/micro-proto v0.0.9/go.mod h1:Cckwmzd89gvS7ThxzZp9kQR/EOdksFQcsTAtDDyKwrg=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
go.unistack.org/micro-proto/v3 v3.1.0 h1:q39FwjFiRZn+Ux/tt+d3bJTmDtsQQWa+3SLYVo1vLfA=
|
||||
go.unistack.org/micro-proto/v3 v3.1.0/go.mod h1:DpRhYCBXlmSJ/AAXTmntvlh7kQkYU6eFvlmYAx4BQS8=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package meter
|
||||
|
||||
//go:generate sh -c "protoc -I./handler -I../ -I$(go list -f '{{ .Dir }}' -m github.com/unistack-org/micro-proto) --go-micro_out='components=micro|http|server',standalone=false,debug=true,paths=source_relative:./handler handler/handler.proto"
|
||||
//go:generate sh -c "protoc -I./handler -I../ -I$(go list -f '{{ .Dir }}' -m go.unistack.org/micro-proto/v3) --go-micro_out='components=micro|http|server',standalone=false,debug=true,paths=source_relative:./handler handler/handler.proto"
|
||||
|
||||
import (
|
||||
|
||||
// import required packages
|
||||
_ "github.com/unistack-org/micro-proto/api"
|
||||
_ "go.unistack.org/micro-proto/v3/api"
|
||||
|
||||
// import required packages
|
||||
_ "github.com/unistack-org/micro-proto/openapiv2"
|
||||
_ "go.unistack.org/micro-proto/v3/openapiv3"
|
||||
)
|
||||
|
@@ -1,24 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package micro.meter.handler;
|
||||
option go_package = "github.com/unistack-org/micro/v3/meter/handler;handler";
|
||||
option go_package = "go.unistack.org/micro/v3/meter/handler;handler";
|
||||
|
||||
import "api/annotations.proto";
|
||||
import "openapiv2/annotations.proto";
|
||||
import "openapiv3/annotations.proto";
|
||||
import "codec/frame.proto";
|
||||
|
||||
service Meter {
|
||||
rpc Metrics(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
option (micro.openapiv3.openapiv3_operation) = {
|
||||
operation_id: "Metrics";
|
||||
responses: {
|
||||
response_code: {
|
||||
name: "default";
|
||||
value: {
|
||||
json_reference: {
|
||||
description: "Error response";
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
default: {
|
||||
reference: {
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@@ -1,12 +1,11 @@
|
||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||
// protoc-gen-go-micro version: v3.4.2
|
||||
// protoc-gen-go-micro version: v3.5.2
|
||||
// source: handler.proto
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
api "go.unistack.org/micro/v3/api"
|
||||
codec "go.unistack.org/micro/v3/codec"
|
||||
)
|
||||
|
@@ -1,12 +1,11 @@
|
||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||
// protoc-gen-go-micro version: v3.4.2
|
||||
// protoc-gen-go-micro version: v3.5.2
|
||||
// source: handler.proto
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
api "go.unistack.org/micro/v3/api"
|
||||
codec "go.unistack.org/micro/v3/codec"
|
||||
server "go.unistack.org/micro/v3/server"
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package server
|
||||
|
||||
//go:generate sh -c "protoc -I./health -I../ -I$(go list -f '{{ .Dir }}' -m github.com/unistack-org/micro-proto) --go-micro_out='components=micro|http|server',standalone=false,debug=true,paths=source_relative:./health health/health.proto"
|
||||
//go:generate sh -c "protoc -I./health -I../ -I$(go list -f '{{ .Dir }}' -m go.unistack.org/micro-proto/v3) --go-micro_out='components=micro|http|server',standalone=false,debug=true,paths=source_relative:./health health/health.proto"
|
||||
|
||||
import (
|
||||
|
||||
// import required packages
|
||||
_ "github.com/unistack-org/micro-proto/api"
|
||||
_ "go.unistack.org/micro-proto/v3/api"
|
||||
|
||||
// import required packages
|
||||
_ "github.com/unistack-org/micro-proto/openapiv2"
|
||||
_ "go.unistack.org/micro-proto/v3/openapiv3"
|
||||
)
|
||||
|
@@ -1,24 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package micro.server.health;
|
||||
option go_package = "github.com/unistack-org/micro/v3/server/health;health";
|
||||
option go_package = "go.unistack.org/micro/v3/server/health;health";
|
||||
|
||||
import "api/annotations.proto";
|
||||
import "openapiv2/annotations.proto";
|
||||
import "openapiv3/annotations.proto";
|
||||
import "codec/frame.proto";
|
||||
|
||||
service Health {
|
||||
rpc Live(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
option (micro.openapiv3.openapiv3_operation) = {
|
||||
operation_id: "Live";
|
||||
responses: {
|
||||
response_code: {
|
||||
name: "default";
|
||||
value: {
|
||||
json_reference: {
|
||||
description: "Error response";
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
default: {
|
||||
reference: {
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -26,16 +22,12 @@ service Health {
|
||||
option (micro.api.http) = { get: "/live"; };
|
||||
};
|
||||
rpc Ready(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
option (micro.openapiv3.openapiv3_operation) = {
|
||||
operation_id: "Ready";
|
||||
responses: {
|
||||
response_code: {
|
||||
name: "default";
|
||||
value: {
|
||||
json_reference: {
|
||||
description: "Error response";
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
default: {
|
||||
reference: {
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -43,16 +35,12 @@ service Health {
|
||||
option (micro.api.http) = { get: "/ready"; };
|
||||
};
|
||||
rpc Version(micro.codec.Frame) returns (micro.codec.Frame) {
|
||||
option (micro.openapiv2.openapiv2_operation) = {
|
||||
option (micro.openapiv3.openapiv3_operation) = {
|
||||
operation_id: "Version";
|
||||
responses: {
|
||||
response_code: {
|
||||
name: "default";
|
||||
value: {
|
||||
json_reference: {
|
||||
description: "Error response";
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
default: {
|
||||
reference: {
|
||||
_ref: "micro.codec.Frame";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@@ -1,12 +1,11 @@
|
||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||
// protoc-gen-go-micro version: v3.4.2
|
||||
// protoc-gen-go-micro version: v3.5.2
|
||||
// source: health.proto
|
||||
|
||||
package health
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
api "go.unistack.org/micro/v3/api"
|
||||
codec "go.unistack.org/micro/v3/codec"
|
||||
)
|
||||
|
@@ -1,12 +1,11 @@
|
||||
// Code generated by protoc-gen-go-micro. DO NOT EDIT.
|
||||
// protoc-gen-go-micro version: v3.4.2
|
||||
// protoc-gen-go-micro version: v3.5.2
|
||||
// source: health.proto
|
||||
|
||||
package health
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
api "go.unistack.org/micro/v3/api"
|
||||
codec "go.unistack.org/micro/v3/codec"
|
||||
server "go.unistack.org/micro/v3/server"
|
||||
|
@@ -69,6 +69,89 @@ func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, e
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
// ZeroFieldByPath clean struct field by its path
|
||||
func ZeroFieldByPath(src interface{}, path string) error {
|
||||
var err error
|
||||
val := reflect.ValueOf(src)
|
||||
|
||||
for _, p := range strings.Split(path, ".") {
|
||||
val, err = structValueByName(val, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if IsEmpty(val) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !val.CanSet() {
|
||||
return ErrInvalidStruct
|
||||
}
|
||||
|
||||
val.Set(reflect.Zero(val.Type()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFieldByPath set struct field by its path
|
||||
func SetFieldByPath(src interface{}, dst interface{}, path string) error {
|
||||
var err error
|
||||
val := reflect.ValueOf(src)
|
||||
|
||||
for _, p := range strings.Split(path, ".") {
|
||||
val, err = structValueByName(val, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !val.CanSet() {
|
||||
return ErrInvalidStruct
|
||||
}
|
||||
|
||||
val.Set(reflect.ValueOf(dst))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// structValueByName get struct field by its name
|
||||
func structValueByName(sv reflect.Value, tkey string) (reflect.Value, error) {
|
||||
if sv.Kind() == reflect.Ptr {
|
||||
sv = sv.Elem()
|
||||
}
|
||||
if sv.Kind() != reflect.Struct {
|
||||
return reflect.Zero(reflect.TypeOf(sv)), ErrInvalidStruct
|
||||
}
|
||||
|
||||
typ := sv.Type()
|
||||
for idx := 0; idx < typ.NumField(); idx++ {
|
||||
fld := typ.Field(idx)
|
||||
val := sv.Field(idx)
|
||||
if len(fld.PkgPath) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if fld.Name == tkey || strings.EqualFold(strings.ToLower(fld.Name), strings.ToLower(tkey)) {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Ptr:
|
||||
if val = val.Elem(); val.Kind() == reflect.Struct {
|
||||
if iface, err := structValueByName(val, tkey); err == nil {
|
||||
return iface, nil
|
||||
}
|
||||
}
|
||||
case reflect.Struct:
|
||||
if iface, err := structValueByName(val, tkey); err == nil {
|
||||
return iface, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return reflect.Zero(reflect.TypeOf(sv)), ErrNotFound
|
||||
}
|
||||
|
||||
// StructFieldByPath get struct field by its path
|
||||
func StructFieldByPath(src interface{}, path string) (interface{}, error) {
|
||||
var err error
|
||||
@@ -98,10 +181,7 @@ func StructFieldByName(src interface{}, tkey string) (interface{}, error) {
|
||||
if len(fld.PkgPath) != 0 {
|
||||
continue
|
||||
}
|
||||
if fld.Name == tkey {
|
||||
if val.Kind() != reflect.Ptr && val.CanAddr() {
|
||||
val = val.Addr()
|
||||
}
|
||||
if fld.Name == tkey || strings.EqualFold(strings.ToLower(fld.Name), strings.ToLower(tkey)) {
|
||||
return val.Interface(), nil
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,80 @@ import (
|
||||
rutil "go.unistack.org/micro/v3/util/reflect"
|
||||
)
|
||||
|
||||
func TestSetFieldByPath(t *testing.T) {
|
||||
type NestedStr struct {
|
||||
BBB string `json:"bbb"`
|
||||
CCC int `json:"ccc"`
|
||||
}
|
||||
type Str1 struct {
|
||||
Name []string `json:"name" codec:"flatten"`
|
||||
XXX string `json:"xxx"`
|
||||
Nested NestedStr `json:"nested"`
|
||||
}
|
||||
type Str2 struct {
|
||||
XXX string `json:"xxx"`
|
||||
Nested *NestedStr `json:"nested"`
|
||||
Name []string `json:"name" codec:"flatten"`
|
||||
}
|
||||
var err error
|
||||
val1 := &Str1{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
|
||||
val2 := &Str2{Name: []string{"first", "second"}, XXX: "ttt", Nested: &NestedStr{BBB: "ddd", CCC: 9}}
|
||||
err = rutil.SetFieldByPath(val1, "xxx", "Nested.BBB")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if val1.Nested.BBB != "xxx" {
|
||||
t.Fatalf("SetFieldByPath not works: %#+v", val1)
|
||||
}
|
||||
err = rutil.SetFieldByPath(val2, "xxx", "Nested.BBB")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if val2.Nested.BBB != "xxx" {
|
||||
t.Fatalf("SetFieldByPath not works: %#+v", val1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestZeroFieldByPath(t *testing.T) {
|
||||
type NestedStr struct {
|
||||
BBB string `json:"bbb"`
|
||||
CCC int `json:"ccc"`
|
||||
}
|
||||
type Str1 struct {
|
||||
Name []string `json:"name" codec:"flatten"`
|
||||
XXX string `json:"xxx"`
|
||||
Nested NestedStr `json:"nested"`
|
||||
}
|
||||
type Str2 struct {
|
||||
XXX string `json:"xxx"`
|
||||
Nested *NestedStr `json:"nested"`
|
||||
Name []string `json:"name" codec:"flatten"`
|
||||
}
|
||||
var err error
|
||||
val1 := &Str1{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
|
||||
|
||||
err = rutil.ZeroFieldByPath(val1, "Nested.BBB")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = rutil.ZeroFieldByPath(val1, "Nested")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if val1.Nested.BBB == "ddd" {
|
||||
t.Fatalf("zero field not works: %v", val1)
|
||||
}
|
||||
|
||||
val2 := &Str2{Name: []string{"first", "second"}, XXX: "ttt", Nested: &NestedStr{BBB: "ddd", CCC: 9}}
|
||||
err = rutil.ZeroFieldByPath(val2, "Nested")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if val2.Nested != nil {
|
||||
t.Fatalf("zero field not works: %v", val2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructFieldsMap(t *testing.T) {
|
||||
type NestedStr struct {
|
||||
BBB string
|
||||
@@ -108,9 +182,9 @@ func TestStructByName(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if v, ok := iface.(*[]string); !ok {
|
||||
t.Fatalf("not *[]string %v", iface)
|
||||
} else if len(*v) != 2 {
|
||||
if v, ok := iface.([]string); !ok {
|
||||
t.Fatalf("not []string %v", iface)
|
||||
} else if len(v) != 2 {
|
||||
t.Fatalf("invalid number %v", iface)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user