diff --git a/cmd/commands.go b/cmd/commands.go new file mode 100644 index 0000000..10caf26 --- /dev/null +++ b/cmd/commands.go @@ -0,0 +1,41 @@ +package main + +import ( + "github.com/spf13/cobra" + "github.com/tenderly/tenderly-cli/cmd/proxy" + "github.com/tenderly/tenderly-cli/config" +) + +var targetHost string +var targetPort string +var targetSchema string +var proxyHost string +var proxyPort string +var path string +var network string + +func init() { + rootCmd.PersistentFlags().StringVar(&targetSchema, "target-schema", "", "Blockchain rpc schema.") + rootCmd.PersistentFlags().StringVar(&targetHost, "target-host", "", "Blockchain rpc host.") + rootCmd.PersistentFlags().StringVar(&targetPort, "target-port", "", "Blockchain rpc port.") + rootCmd.PersistentFlags().StringVar(&proxyHost, "proxy-host", "", "Proxy host.") + rootCmd.PersistentFlags().StringVar(&proxyPort, "proxy-port", "", "Proxy port.") + rootCmd.PersistentFlags().StringVar(&path, "path", "", "Path to the project build folder.") + rootCmd.PersistentFlags().StringVar(&network, "network", "", "Network id.") + + rootCmd.AddCommand(proxyCmd) +} + +var rootCmd = &cobra.Command{ + Use: "tenderly", + Short: "Tenderly helps you observe your contracts in any environment.", + Long: "Tenderly is a development tool for smart contract.", +} + +var proxyCmd = &cobra.Command{ + Use: "proxy", + Short: "Proxy", + Run: func(cmd *cobra.Command, args []string) { + proxy.Start(targetSchema, targetHost, targetPort, proxyHost, proxyPort, path, network) + }, +} diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..7704989 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + "os" +) + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(0) + } +} + +func main() { + Execute() +} diff --git a/cmd/proxy/handler.go b/cmd/proxy/handler.go new file mode 100644 index 0000000..d255281 --- /dev/null +++ b/cmd/proxy/handler.go @@ -0,0 +1,79 @@ +package proxy + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "net/http/httputil" + "time" +) + +type myTransport struct { + // Uncomment this if you want to capture the transport + // CapturedTransport http.RoundTripper +} +type Montioringpath struct { + Path string + Count int64 + Duration int64 + AverageTime int64 +} + +var globalMap = make(map[string]Montioringpath) + +func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) { + + fmt.Println("---------------------------New Request--------------------------------------------------") + buf, _ := ioutil.ReadAll(request.Body) + rdr1 := ioutil.NopCloser(bytes.NewBuffer(buf)) + rdr2 := ioutil.NopCloser(bytes.NewBuffer(buf)) + + fmt.Println("Request body : ", rdr1) + request.Body = rdr2 // OK since rdr2 implements the + + start := time.Now() + response, err := http.DefaultTransport.RoundTrip(request) + if err != nil { + print("\n\ncame in error resp here", err) + return nil, err //Server is not reachable. Server not working + } + elapsed := time.Since(start) + + key := request.Method + "-" + request.URL.Path //for example for POST Method with /path1 as url path key=POST-/path1 + + if val, ok := globalMap[key]; ok { + val.Count = val.Count + 1 + val.Duration += elapsed.Nanoseconds() + val.AverageTime = val.Duration / val.Count + globalMap[key] = val + //do something here + } else { + var m Montioringpath + m.Path = request.URL.Path + m.Count = 1 + m.Duration = elapsed.Nanoseconds() + m.AverageTime = m.Duration / m.Count + globalMap[key] = m + } + b, err := json.MarshalIndent(globalMap, "", " ") + if err != nil { + fmt.Println("error:", err) + } + + body, err := httputil.DumpResponse(response, true) + if err != nil { + print("\n\nerror in dumb response") + // copying the response body did not work + return nil, err + } + + log.Println("Response Body : ", string(body)) + log.Println("Response Time:", elapsed.Nanoseconds()) + + fmt.Println("Analysis on different Path :", string(b)) + + return response, err +} diff --git a/cmd/proxy/proxy.go b/cmd/proxy/proxy.go new file mode 100644 index 0000000..82d7296 --- /dev/null +++ b/cmd/proxy/proxy.go @@ -0,0 +1,49 @@ +package proxy + +import ( + "flag" + "fmt" + "log" + "net/http" + "net/http/httputil" + "net/url" +) + +type Prox struct { + target *url.URL + proxy *httputil.ReverseProxy +} + +func NewProxy(target string) *Prox { + url, _ := url.Parse(target) + + return &Prox{target: url, proxy: httputil.NewSingleHostReverseProxy(url)} +} + +func (p *Prox) handle(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-GoProxy", "GoProxy") + p.proxy.Transport = &myTransport{} + + p.proxy.ServeHTTP(w, r) + +} + +func Start(targetSchema, targetHost, targetPort, proxyHost, proxyPort, path, network string) { + flag.Parse() + + fmt.Println(fmt.Sprintf("server will run on %s:%s", proxyHost, proxyPort)) + fmt.Println(fmt.Sprintf("redirecting to %s:%s", targetHost, targetPort)) + + // proxy + proxy := NewProxy(targetSchema + "://" + targetHost + ":" + targetPort) + + http.HandleFunc("/proxyServer", Server) + + // server redirection + http.HandleFunc("/", proxy.handle) + log.Fatal(http.ListenAndServe(proxyHost+":"+proxyPort, nil)) +} + +func Server(w http.ResponseWriter, r *http.Request) { + +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8beddfa --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/Tenderly/tenderly-cli + +require gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ec36818 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153 h1:i2sumy6EgvN2dbX7HPhoDc7hLyoym3OYdU5HlvUUrpE= +gopkg.in/elazarl/goproxy.v1 v1.0.0-20180725130230-947c36da3153/go.mod h1:xzjpkyedLMz3EXUTBbkRuuGPsxfsBX3Sy7J6kC9Gvoc=