Skip to content

Commit

Permalink
Merge pull request #230 from devopsfaith/flatmap_formatter
Browse files Browse the repository at this point in the history
Flatmap formatter
  • Loading branch information
kpacha committed Mar 25, 2019
2 parents 261b7d8 + 6071988 commit d78009a
Show file tree
Hide file tree
Showing 8 changed files with 560 additions and 40 deletions.
48 changes: 45 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 4 additions & 27 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,3 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true


[[constraint]]
name = "github.com/gin-gonic/gin"
version = "1.2.0"
Expand All @@ -45,6 +18,10 @@
name = "github.com/go-chi/chi"
version = "4.0.1"

[[constraint]]
name = "github.com/devopsfaith/flatmap"
branch = "master"

[prune]
go-tests = true
unused-packages = true
93 changes: 93 additions & 0 deletions proxy/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package proxy
import (
"strings"

"github.com/devopsfaith/flatmap/tree"
"github.com/devopsfaith/krakend/config"
)

Expand All @@ -28,6 +29,10 @@ type entityFormatter struct {

// NewEntityFormatter creates an entity formatter with the received backend definition
func NewEntityFormatter(remote *config.Backend) EntityFormatter {
if ef := newFlatmapFormatter(remote); ef != nil {
return ef
}

var propertyFilter propertyFilter
if len(remote.Whitelist) > 0 {
propertyFilter = newWhitelistingFilter(remote.Whitelist)
Expand Down Expand Up @@ -179,3 +184,91 @@ func blacklistFilterSub(v interface{}, blacklist []string) map[string]interface{
}
return tmp
}

const flatmapKey = "flatmap_filter"

type flatmapFormatter struct {
Target string
Prefix string
Ops []flatmapOp
}

type flatmapOp struct {
Type string
Args [][]string
}

// Format implements the EntityFormatter interface
func (e flatmapFormatter) Format(entity Response) Response {
if e.Target != "" {
extractTarget(e.Target, &entity)
}

e.processOps(&entity)

if e.Prefix != "" {
entity.Data = map[string]interface{}{e.Prefix: entity.Data}
}
return entity
}

func (e flatmapFormatter) processOps(entity *Response) {
flatten, err := tree.New(entity.Data)
if err != nil {
return
}
for _, op := range e.Ops {
switch op.Type {
case "move":
flatten.Move(op.Args[0], op.Args[1])
case "del":
flatten.Del(op.Args[0])
default:
}
}

entity.Data, _ = flatten.Get([]string{}).(map[string]interface{})
}

func newFlatmapFormatter(remote *config.Backend) EntityFormatter {
if v, ok := remote.ExtraConfig[Namespace]; ok {
if e, ok := v.(map[string]interface{}); ok {
if vs, ok := e[flatmapKey].([]interface{}); ok {
if len(vs) == 0 {
return nil
}
ops := []flatmapOp{}
for _, v := range vs {
m, ok := v.(map[string]interface{})
if !ok {
continue
}
op := flatmapOp{}
if t, ok := m["type"].(string); ok {
op.Type = t
} else {
continue
}
if args, ok := m["args"].([]interface{}); ok {
op.Args = make([][]string, len(args))
for k, arg := range args {
if t, ok := arg.(string); ok {
op.Args[k] = strings.Split(t, ".")
}
}
}
ops = append(ops, op)
}
if len(ops) == 0 {
return nil
}
return &flatmapFormatter{
Target: remote.Target,
Prefix: remote.Group,
Ops: ops,
}
}
}
}
return nil
}
64 changes: 64 additions & 0 deletions proxy/formatter_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,67 @@ func BenchmarkEntityFormatter_mapping(b *testing.B) {
}
}
}

func BenchmarkEntityFormatter_flatmap(b *testing.B) {
sub := map[string]interface{}{
"b": true,
"c": 42,
"d": "tupu",
"e": []interface{}{1, 2, 3, 4},
}
sample := Response{
Data: map[string]interface{}{
"content": map[string]interface{}{
"supu": 42,
"tupu": false,
"foo": "bar",
"a": sub,
"collection": []interface{}{sub, sub, sub, sub},
},
},
IsComplete: true,
}
f := NewEntityFormatter(&config.Backend{
Target: "content",
Group: "group",
ExtraConfig: config.ExtraConfig{
Namespace: map[string]interface{}{
flatmapKey: []interface{}{
map[string]interface{}{
"type": "del",
"args": []interface{}{"c"},
},
map[string]interface{}{
"type": "move",
"args": []interface{}{"supu", "SUPUUUUU"},
},
map[string]interface{}{
"type": "move",
"args": []interface{}{"a.b", "a.BOOOOO"},
},
map[string]interface{}{
"type": "del",
"args": []interface{}{"collection.*.b"},
},
map[string]interface{}{
"type": "del",
"args": []interface{}{"collection.*.d"},
},
map[string]interface{}{
"type": "del",
"args": []interface{}{"collection.*.e"},
},
map[string]interface{}{
"type": "move",
"args": []interface{}{"collection.*.c", "collection.*.x"},
},
},
},
},
})
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
f.Format(sample)
}
}
Loading

0 comments on commit d78009a

Please sign in to comment.