api/router/static: allow to specify body dst (#1486)

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-04-07 17:38:27 +03:00 committed by GitHub
parent aaee01b1a7
commit 6aaad7d63f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 2 deletions

View File

@ -22,7 +22,7 @@ type Api interface {
String() string
}
type Options struct {}
type Options struct{}
type Option func(*Options) error
@ -40,6 +40,10 @@ type Endpoint struct {
Method []string
// HTTP Path e.g /greeter. Expect POSIX regex
Path []string
// Body destination
// "*" or "" - top level message value
// "string" - inner message value
Body string
// Stream flag
Stream bool
}

View File

@ -300,6 +300,7 @@ func requestPayload(r *http.Request) ([]byte, error) {
// allocate maximum
matches := make(map[string]interface{}, len(md))
bodydst := ""
// get fields from url path
for k, v := range md {
@ -307,6 +308,9 @@ func requestPayload(r *http.Request) ([]byte, error) {
if strings.HasPrefix(k, "x-api-field-") {
matches[strings.TrimPrefix(k, "x-api-field-")] = v
delete(md, k)
} else if k == "x-api-body" {
bodydst = v
delete(md, k)
}
}
@ -387,8 +391,32 @@ func requestPayload(r *http.Request) ([]byte, error) {
} else {
return []byte{}, nil
}
if bodydst == "" || bodydst == "*" {
if out, err = jsonpatch.MergeMergePatches(out, bodybuf); err == nil {
return out, nil
}
}
dstmap := make(map[string]interface{})
ps := strings.Split(bodydst, ".")
if len(ps) == 1 {
dstmap[ps[0]] = bodybuf
} else {
em := make(map[string]interface{})
em[ps[len(ps)-1]] = bodybuf
for i := len(ps) - 2; i > 0; i-- {
nm := make(map[string]interface{})
nm[ps[i]] = em
em = nm
}
dstmap[ps[0]] = em
}
if out, err = jsonpatch.MergeMergePatches(out, bodybuf); err == nil {
bodyout, err := json.Marshal(dstmap)
if err != nil {
return nil, err
}
if out, err = jsonpatch.MergeMergePatches(out, bodyout); err == nil {
return out, nil
}

View File

@ -191,6 +191,7 @@ func (r *staticRouter) Endpoint(req *http.Request) (*api.Service, error) {
Host: ep.apiep.Host,
Method: ep.apiep.Method,
Path: ep.apiep.Path,
Body: ep.apiep.Body,
Stream: ep.apiep.Stream,
},
Services: services,
@ -274,6 +275,7 @@ func (r *staticRouter) endpoint(req *http.Request) (*endpoint, error) {
for k, v := range matches {
md[fmt.Sprintf("x-api-field-%s", k)] = v
}
md["x-api-body"] = ep.apiep.Body
*req = *req.Clone(context.WithValue(ctx, metadata.MetadataKey{}, md))
break pathLoop
}
@ -285,6 +287,7 @@ func (r *staticRouter) endpoint(req *http.Request) (*endpoint, error) {
// we got here, so its a match
return ep, nil
}
// no match
return nil, fmt.Errorf("endpoint not found for %v", req)
}