diff --git a/core/post_script.go b/core/post_script.go new file mode 100644 index 0000000..7512f7e --- /dev/null +++ b/core/post_script.go @@ -0,0 +1,32 @@ +package core + +import ( + "bytes" + "encoding/json" + "strings" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +type PostScriptConfig struct { + Func string `json:"func"` + Src []string `json:"src"` + Dst []string `json:"dst"` +} + +const ( + FuncNameStringToJson string = "stringToJSON" +) + +var FuncStringToJson = func(in string, src, dst []string) string { + + vStr := gjson.Get(in, strings.Join(src, ".")) + + resStr, _ := sjson.SetRaw(in, strings.Join(dst, "."), vStr.String()) + + var resBuf bytes.Buffer + json.Indent(&resBuf, []byte(resStr), "", " ") + + return resBuf.String() +} diff --git a/core/resource.go b/core/resource.go index 33d5c38..e284296 100644 --- a/core/resource.go +++ b/core/resource.go @@ -3,6 +3,7 @@ package core import ( "bytes" "context" + "encoding/json" "fmt" "io" "io/ioutil" @@ -34,6 +35,9 @@ type Resource struct { protos []Proto protosets []Proto + postScriptsSvc map[string]bool + postScriptsMtd map[string][]PostScriptConfig + headers []string md metadata.MD } @@ -112,9 +116,9 @@ func (r *Resource) List(symbol string) ([]string, error) { return result, fmt.Errorf("No Services") } - for _, svc := range svcs { - result = append(result, fmt.Sprintf("%s\n", svc)) - } + result = append(result, svcs...) + + r.loadPostScriptsServices() } else { methods, err := grpcurl.ListMethods(r.descSource, symbol) if err != nil { @@ -124,14 +128,47 @@ func (r *Resource) List(symbol string) ([]string, error) { return result, fmt.Errorf("No Function") // probably unlikely } - for _, m := range methods { - result = append(result, fmt.Sprintf("%s\n", m)) - } + result = append(result, methods...) + + r.loadPostScriptsMethods(symbol) } return result, nil } +func (r *Resource) loadPostScriptsServices() { + pwd, _ := os.Getwd() + dir, _ := os.ReadDir(pwd + "/core/post-scripts") + r.postScriptsSvc = make(map[string]bool) + for _, v := range dir { + r.postScriptsSvc[v.Name()] = true + } +} + +func (r *Resource) loadPostScriptsMethods(symbol string) { + if ok := r.postScriptsSvc[symbol]; !ok { + return + } + pwd, _ := os.Getwd() + dirName := pwd + "/core/post-scripts/" + symbol + dir, _ := os.ReadDir(dirName) + + r.postScriptsMtd = make(map[string][]PostScriptConfig) + + for _, v := range dir { + mtd := symbol + "." + v.Name() + + f, _ := os.Open(dirName + "/" + v.Name()) + + defer f.Close() + + cfgs := []PostScriptConfig{} + if err := json.NewDecoder(f).Decode(&cfgs); err == nil { + r.postScriptsMtd[mtd] = cfgs + } + } +} + // Describe - The "describe" verb will print the type of any symbol that the server knows about // or that is found in a given protoset file. // It also prints a description of that symbol, in the form of snippets of proto source. @@ -217,7 +254,7 @@ func (r *Resource) Invoke(ctx context.Context, metadata []string, symbol string, start := time.Now() err = grpcurl.InvokeRPC(ctx, r.descSource, r.clientConn, symbol, headers, h, rf.Next) - end := time.Now().Sub(start) / time.Millisecond + end := time.Since(start) if err != nil { return "", end, err } @@ -229,6 +266,23 @@ func (r *Resource) Invoke(ctx context.Context, metadata []string, symbol string, return resultBuffer.String(), end, nil } +func (r *Resource) PostScript(ctx context.Context, symbol, resp string) string { + cfgs, ok := r.postScriptsMtd[symbol] + if !ok { + return "" + } + + var res string = resp + for _, cfg := range cfgs { + switch cfg.Func { + case FuncNameStringToJson: + res = FuncStringToJson(res, cfg.Src, cfg.Dst) + } + } + + return res +} + // Close - to close all resources that was opened before func (r *Resource) Close() { var wg sync.WaitGroup diff --git a/go.mod b/go.mod index acd0b7a..72065f2 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,7 @@ require ( github.com/fullstorydev/grpcurl v1.3.2 github.com/gorilla/mux v1.7.0 github.com/jhump/protoreflect v1.5.0 + github.com/tidwall/gjson v1.17.1 + github.com/tidwall/sjson v1.2.5 google.golang.org/grpc v1.21.0 ) diff --git a/go.sum b/go.sum index 733c56f..5748f76 100644 --- a/go.sum +++ b/go.sum @@ -12,10 +12,17 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gusaul/grpcox v0.0.0-20190913075147-1890be43b9f3 h1:NjksNPWX5m6TNpjioyXkq3SoRu8bemSVpts+sR6qkSQ= -github.com/gusaul/grpcox v0.0.0-20190913075147-1890be43b9f3/go.mod h1:blSZjUt+13dX6OtwGTeCrV2iW0WNDMLox0TWkdVuUXE= github.com/jhump/protoreflect v1.5.0 h1:NgpVT+dX71c8hZnxHof2M7QDK7QtohIJ7DYycjnkyfc= github.com/jhump/protoreflect v1.5.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/handler/handler.go b/handler/handler.go index dbd11e9..4b76ff2 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -266,14 +266,20 @@ func (h *Handler) invokeFunction(w http.ResponseWriter, r *http.Request) { return } + postScriptResult := res.PostScript(context.Background(), funcName, result) + type invRes struct { Time string `json:"timer"` Result string `json:"result"` + + PostScriptsResult string `json:"post_script_result"` } h.g.Extend(host) response(w, invRes{ Time: timer.String(), Result: result, + + PostScriptsResult: postScriptResult, }) } diff --git a/index/css/style.css b/index/css/style.css index 4e4b66e..cef252b 100644 --- a/index/css/style.css +++ b/index/css/style.css @@ -1,55 +1,72 @@ body { padding-bottom: 50px; } + .mt-10 { - margin-top:10px; + margin-top: 10px; } + .pt-50 { - padding-top:50px; + padding-top: 50px; } + .w-120 { width: 120px; } + .custom-pretty { - border:none!important; + border: none !important; } + .custom-control-label:hover { cursor: pointer; } -#choose-service, #choose-function, #body-request { + +#choose-service, +#choose-function, +#body-request { margin-top: 40px; } + .schema-body { height: 250px; overflow-y: scroll; } -#response { + +#resp-tab { margin-top: 30px; } /* github corner */ -.github-corner:hover .octo-arm{ - animation:octocat-wave 560ms ease-in-out +.github-corner:hover .octo-arm { + animation: octocat-wave 560ms ease-in-out } -@keyframes octocat-wave{ - 0%,100%{ - transform:rotate(0) + +@keyframes octocat-wave { + + 0%, + 100% { + transform: rotate(0) } - 20%,60%{ - transform:rotate(-25deg) + + 20%, + 60% { + transform: rotate(-25deg) } - 40%,80%{ - transform:rotate(10deg) + + 40%, + 80% { + transform: rotate(10deg) } } -@media (max-width:500px){ - .github-corner:hover .octo-arm{ - animation:none +@media (max-width:500px) { + .github-corner:hover .octo-arm { + animation: none } - .github-corner .octo-arm{ - animation:octocat-wave 560ms ease-in-out + .github-corner .octo-arm { + animation: octocat-wave 560ms ease-in-out } } @@ -62,15 +79,16 @@ body { position: fixed; top: 200px; z-index: 100; - -webkit-box-shadow: -3px 0px 5px 0px rgba(0,0,0,0.2); - box-shadow: -3px 0px 5px 0px rgba(0,0,0,0.2); + -webkit-box-shadow: -3px 0px 5px 0px rgba(0, 0, 0, 0.2); + box-shadow: -3px 0px 5px 0px rgba(0, 0, 0, 0.2); left: -190px; transition: all .3s; -webkit-transition: all .3s; color: #222; } -.connections:hover, .connections:focus { +.connections:hover, +.connections:focus { transform: translate3d(190px, 0, 0); animation-timing-function: 1s ease-in } @@ -110,7 +128,9 @@ body { cursor: pointer; } -.connections .nav li a:hover { color: #aaa } +.connections .nav li a:hover { + color: #aaa +} .dots { position: absolute; @@ -141,6 +161,7 @@ circle { stroke-opacity: 1; transform: scale(0.3); } + to { stroke-width: 0; stroke-opacity: 0; @@ -157,7 +178,7 @@ circle { font-size: 80px; } -.spinner > div { +.spinner>div { background-color: #59698d; height: 100%; width: 18px; @@ -188,15 +209,28 @@ circle { } @-webkit-keyframes sk-stretchdelay { - 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } - 20% { -webkit-transform: scaleY(1.0) } + + 0%, + 40%, + 100% { + -webkit-transform: scaleY(0.4) + } + + 20% { + -webkit-transform: scaleY(1.0) + } } @keyframes sk-stretchdelay { - 0%, 40%, 100% { + + 0%, + 40%, + 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); - } 20% { + } + + 20% { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); } @@ -215,13 +249,14 @@ circle { margin-bottom: 0; margin-left: 5px; max-width: 100%; - white-space:nowrap; - overflow:hidden; - text-overflow:ellipsis; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } + .one-long-line:hover { cursor: pointer; - overflow:visible; + overflow: visible; } .column-row-left { @@ -230,7 +265,7 @@ circle { margin-top: 8px; } -.column-row-left .md-form{ +.column-row-left .md-form { margin-bottom: 0; } @@ -248,5 +283,65 @@ circle { } .request-list.selected { - background: #dadfe3;; + background: #dadfe3; + ; +} + +/* Style the tab */ +.tab { + overflow: hidden; + /* border: 1px solid #ccc; */ + /* background-color: #f1f1f1; */ +} + +/* Style the buttons inside the tab */ +.tab button { + background-color: inherit; + float: left; + border: none; + outline: none; + cursor: pointer; + padding: 14px 16px; + transition: 0.3s; + font-size: 17px; +} + +/* Change background color of buttons on hover */ +.tab button:hover { + background-color: #ddd; +} + +/* Create an active/current tablink class */ +.tab button.active { + background-color: #ccc; +} + + +/* Style the tab content */ +.tabcontent { + /* display: none; */ + padding: 6px 12px; + -webkit-animation: fadeEffect 1s; + animation: fadeEffect 1s; +} + +/* Fade in tabs */ +@-webkit-keyframes fadeEffect { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes fadeEffect { + from { + opacity: 0; + } + + to { + opacity: 1; + } } \ No newline at end of file diff --git a/index/index.html b/index/index.html index 4c5f95d..4b4d5cd 100644 --- a/index/index.html +++ b/index/index.html @@ -1,5 +1,6 @@ +
@@ -35,10 +36,12 @@