fix path template parsing
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
5f029fd432
commit
09e7282b2b
2
go.mod
2
go.mod
@ -2,4 +2,4 @@ module github.com/unistack-org/micro-client-http/v3
|
||||
|
||||
go 1.16
|
||||
|
||||
require github.com/unistack-org/micro/v3 v3.5.2
|
||||
require github.com/unistack-org/micro/v3 v3.5.4
|
||||
|
4
go.sum
4
go.sum
@ -5,8 +5,8 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
|
||||
github.com/unistack-org/micro/v3 v3.5.2 h1:8b9Mk4FLWRLp8SduBh5Xs6g/3xJ+ZIBOnH82eHuLWnw=
|
||||
github.com/unistack-org/micro/v3 v3.5.2/go.mod h1:1ZkwpEqpiHiVhM2hiF9DamtpsF04oFybFhEQ4zEMcro=
|
||||
github.com/unistack-org/micro/v3 v3.5.4 h1:6nIljqND355f+Fhc2mtCxYb5IRwer6nsMoAXpN8kka0=
|
||||
github.com/unistack-org/micro/v3 v3.5.4/go.mod h1:1ZkwpEqpiHiVhM2hiF9DamtpsF04oFybFhEQ4zEMcro=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
79
http.go
79
http.go
@ -532,50 +532,61 @@ func (h *httpClient) Stream(ctx context.Context, req client.Request, opts ...cli
|
||||
return nil, grr
|
||||
}
|
||||
|
||||
func (h *httpClient) BatchPublish(ctx context.Context, p []client.Message, opts ...client.PublishOption) error {
|
||||
return h.publish(ctx, p, opts...)
|
||||
}
|
||||
|
||||
func (h *httpClient) Publish(ctx context.Context, p client.Message, opts ...client.PublishOption) error {
|
||||
return h.publish(ctx, []client.Message{p}, opts...)
|
||||
}
|
||||
|
||||
func (h *httpClient) publish(ctx context.Context, ps []client.Message, opts ...client.PublishOption) error {
|
||||
options := client.NewPublishOptions(opts...)
|
||||
|
||||
md, ok := metadata.FromOutgoingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.New(2)
|
||||
}
|
||||
md[metadata.HeaderContentType] = p.ContentType()
|
||||
md[metadata.HeaderTopic] = p.Topic()
|
||||
|
||||
cf, err := h.newCodec(p.ContentType())
|
||||
if err != nil {
|
||||
return errors.InternalServerError("go.micro.client", err.Error())
|
||||
// get proxy
|
||||
exchange := ""
|
||||
if v, ok := os.LookupEnv("MICRO_PROXY"); ok {
|
||||
exchange = v
|
||||
}
|
||||
|
||||
var body []byte
|
||||
msgs := make([]*broker.Message, 0, len(ps))
|
||||
|
||||
// passed in raw data
|
||||
if d, ok := p.Payload().(*codec.Frame); ok {
|
||||
body = d.Data
|
||||
} else {
|
||||
b := bytes.NewBuffer(nil)
|
||||
if err := cf.Write(b, &codec.Message{Type: codec.Event}, p.Payload()); err != nil {
|
||||
for _, p := range ps {
|
||||
md, ok := metadata.FromOutgoingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.New(2)
|
||||
}
|
||||
md[metadata.HeaderContentType] = p.ContentType()
|
||||
md[metadata.HeaderTopic] = p.Topic()
|
||||
|
||||
cf, err := h.newCodec(p.ContentType())
|
||||
if err != nil {
|
||||
return errors.InternalServerError("go.micro.client", err.Error())
|
||||
}
|
||||
body = b.Bytes()
|
||||
|
||||
var body []byte
|
||||
|
||||
// passed in raw data
|
||||
if d, ok := p.Payload().(*codec.Frame); ok {
|
||||
body = d.Data
|
||||
} else {
|
||||
b := bytes.NewBuffer(nil)
|
||||
if err := cf.Write(b, &codec.Message{Type: codec.Event}, p.Payload()); err != nil {
|
||||
return errors.InternalServerError("go.micro.client", err.Error())
|
||||
}
|
||||
body = b.Bytes()
|
||||
}
|
||||
|
||||
topic := p.Topic()
|
||||
if len(exchange) > 0 {
|
||||
topic = exchange
|
||||
}
|
||||
|
||||
md.Set(metadata.HeaderTopic, topic)
|
||||
msgs = append(msgs, &broker.Message{Header: md, Body: body})
|
||||
}
|
||||
|
||||
topic := p.Topic()
|
||||
|
||||
// get proxy
|
||||
if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 {
|
||||
options.Exchange = prx
|
||||
}
|
||||
|
||||
// get the exchange
|
||||
if len(options.Exchange) > 0 {
|
||||
topic = options.Exchange
|
||||
}
|
||||
|
||||
return h.opts.Broker.Publish(ctx, topic, &broker.Message{
|
||||
Header: md,
|
||||
Body: body,
|
||||
},
|
||||
return h.opts.Broker.BatchPublish(ctx, msgs,
|
||||
broker.PublishContext(ctx),
|
||||
broker.PublishBodyOnly(options.BodyOnly),
|
||||
)
|
||||
|
38
util.go
38
util.go
@ -14,11 +14,10 @@ import (
|
||||
"github.com/unistack-org/micro/v3/errors"
|
||||
"github.com/unistack-org/micro/v3/logger"
|
||||
rutil "github.com/unistack-org/micro/v3/util/reflect"
|
||||
util "github.com/unistack-org/micro/v3/util/router"
|
||||
)
|
||||
|
||||
var (
|
||||
templateCache = make(map[string]util.Template)
|
||||
templateCache = make(map[string][]string)
|
||||
mu sync.RWMutex
|
||||
)
|
||||
|
||||
@ -46,14 +45,17 @@ func newPathRequest(path string, method string, body string, msg interface{}, ta
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if len(tpl.Fields) > 0 && msg == nil {
|
||||
if len(tpl) > 0 && msg == nil {
|
||||
return "", nil, fmt.Errorf("nil message but path params requested: %v", path)
|
||||
}
|
||||
|
||||
fieldsmapskip := make(map[string]struct{})
|
||||
fieldsmap := make(map[string]string, len(tpl.Fields))
|
||||
for _, v := range tpl.Fields {
|
||||
fieldsmap[v] = ""
|
||||
fieldsmap := make(map[string]string, len(tpl))
|
||||
for _, v := range tpl {
|
||||
if v[0] != '{' || v[len(v)-1] != '}' {
|
||||
continue
|
||||
}
|
||||
fieldsmap[v[1:len(v)-1]] = ""
|
||||
}
|
||||
|
||||
nmsg, err := rutil.Zero(msg)
|
||||
@ -149,11 +151,15 @@ func newPathRequest(path string, method string, body string, msg interface{}, ta
|
||||
}
|
||||
|
||||
var b strings.Builder
|
||||
for _, fld := range tpl.Pool {
|
||||
for _, fld := range tpl {
|
||||
_, _ = b.WriteRune('/')
|
||||
if v, ok := fieldsmap[fld]; ok {
|
||||
if v != "" {
|
||||
_, _ = b.WriteString(v)
|
||||
if fld[0] == '{' && fld[len(fld)-1] == '}' {
|
||||
if v, ok := fieldsmap[fld[1:len(fld)-1]]; ok {
|
||||
if v != "" {
|
||||
_, _ = b.WriteString(v)
|
||||
}
|
||||
} else {
|
||||
_, _ = b.WriteString(fld)
|
||||
}
|
||||
} else {
|
||||
_, _ = b.WriteString(fld)
|
||||
@ -172,7 +178,10 @@ func newPathRequest(path string, method string, body string, msg interface{}, ta
|
||||
return b.String(), nmsg, nil
|
||||
}
|
||||
|
||||
func newTemplate(path string) (util.Template, error) {
|
||||
func newTemplate(path string) ([]string, error) {
|
||||
if len(path) == 0 || path[0] != '/' {
|
||||
return nil, fmt.Errorf("path must starts with /")
|
||||
}
|
||||
mu.RLock()
|
||||
tpl, ok := templateCache[path]
|
||||
if ok {
|
||||
@ -181,12 +190,7 @@ func newTemplate(path string) (util.Template, error) {
|
||||
}
|
||||
mu.RUnlock()
|
||||
|
||||
rule, err := util.Parse(path)
|
||||
if err != nil {
|
||||
return tpl, err
|
||||
}
|
||||
|
||||
tpl = rule.Compile()
|
||||
tpl = strings.Split(path[1:], "/")
|
||||
mu.Lock()
|
||||
templateCache[path] = tpl
|
||||
mu.Unlock()
|
||||
|
30
util_test.go
30
util_test.go
@ -5,13 +5,31 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTemplate(t *testing.T) {
|
||||
tpl, err := newTemplate("/v1/{ClientID}/list")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
func TestParsing(t *testing.T) {
|
||||
type Message struct {
|
||||
IIN string `protobuf:"bytes,1,opt,name=iin,proto3" json:"iin"`
|
||||
}
|
||||
|
||||
omsg := &Message{IIN: "5555"}
|
||||
|
||||
for _, m := range []string{"POST"} {
|
||||
body := ""
|
||||
path, nmsg, err := newPathRequest("/users/iin/{iin}/push-notifications", m, body, omsg, []string{"protobuf", "json"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
u, err := url.Parse(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = nmsg
|
||||
if u.Path != "/users/iin/5555/push-notifications" {
|
||||
t.Fatalf("newPathRequest invalid path %s", u.Path)
|
||||
}
|
||||
if nmsg != nil {
|
||||
t.Fatalf("new message must be nil: %v\n", nmsg)
|
||||
}
|
||||
}
|
||||
_ = tpl
|
||||
// fmt.Printf("%#+v\n", tpl.Pool)
|
||||
}
|
||||
|
||||
func TestNewPathRequest(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user