zyxxoo commented on code in PR #514:
URL: 
https://github.com/apache/incubator-hugegraph-toolchain/pull/514#discussion_r1309528959


##########
hugegraph-client-go/Makefile:
##########
@@ -0,0 +1,58 @@
+# init project path
+HOMEDIR := $(shell pwd)
+OUTDIR  := $(HOMEDIR)/output
+
+# 设置编译时所需要的 go 环境
+export GOENV = $(HOMEDIR)/go.env
+
+GO      := go

Review Comment:
   GO              := GO111MODULE=on go



##########
hugegraph-client-go/Makefile:
##########
@@ -0,0 +1,58 @@
+# init project path
+HOMEDIR := $(shell pwd)
+OUTDIR  := $(HOMEDIR)/output
+
+# 设置编译时所需要的 go 环境
+export GOENV = $(HOMEDIR)/go.env
+
+GO      := go
+GOMOD   := $(GO) mod
+GOBUILD := $(GO) build
+GOTEST  := $(GO) test -race -timeout 30s -gcflags="-N -l"
+GOPKGS  := $$($(GO) list ./...| grep -vE "vendor")
+
+# test cover files
+COVPROF := $(HOMEDIR)/covprof.out  # coverage profile
+COVFUNC := $(HOMEDIR)/covfunc.txt  # coverage profile information for each 
function
+COVHTML := $(HOMEDIR)/covhtml.html # HTML representation of coverage profile
+
+# make, make all
+all: prepare compile package
+
+set-env:

Review Comment:
   print-env?



##########
hugegraph-client-go/Makefile:
##########
@@ -0,0 +1,58 @@
+# init project path
+HOMEDIR := $(shell pwd)
+OUTDIR  := $(HOMEDIR)/output
+
+# 设置编译时所需要的 go 环境
+export GOENV = $(HOMEDIR)/go.env
+
+GO      := go
+GOMOD   := $(GO) mod
+GOBUILD := $(GO) build
+GOTEST  := $(GO) test -race -timeout 30s -gcflags="-N -l"
+GOPKGS  := $$($(GO) list ./...| grep -vE "vendor")
+
+# test cover files
+COVPROF := $(HOMEDIR)/covprof.out  # coverage profile
+COVFUNC := $(HOMEDIR)/covfunc.txt  # coverage profile information for each 
function
+COVHTML := $(HOMEDIR)/covhtml.html # HTML representation of coverage profile
+
+# make, make all
+all: prepare compile package
+
+set-env:
+       $(GO) env 
+
+
+#make prepare, download dependencies
+prepare: gomod
+
+gomod: set-env

Review Comment:
   gomod maybe rename tidy or download?



##########
hugegraph-client-go/hgtransport/hgtransport.go:
##########
@@ -0,0 +1,246 @@
+package hgtransport
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "regexp"
+       "runtime"
+       "strings"
+       "time"
+
+       "hugegraph.apache.org/client-go/internal/version"
+)
+
+// Version returns the package version as a string.
+//
+const Version = version.Client
+
+var (
+       userAgent   string
+       reGoVersion = regexp.MustCompile(`go(\d+\.\d+\..+)`)
+)
+
+func init() {
+       userAgent = initUserAgent()
+}
+
+// Interface defines the interface for HTTP client.
+//
+type Interface interface {
+       Perform(*http.Request) (*http.Response, error)
+}
+
+// Config represents the configuration of HTTP client.
+//
+type Config struct {
+       URL        *url.URL
+       Username   string
+       Password   string
+       GraphSpace string
+       Graph      string
+
+       Transport http.RoundTripper
+       Logger    Logger
+}
+
+// Client represents the HTTP client.
+//
+type Client struct {
+       url         *url.URL
+       username    string
+       password    string
+       graphspaces string
+       graph       string
+
+       transport http.RoundTripper
+       logger    Logger
+}
+
+// New creates new HTTP client.
+//
+// http.DefaultTransport will be used if no transport is passed in the 
configuration.
+//
+func New(cfg Config) *Client {
+       if cfg.Transport == nil {
+               cfg.Transport = http.DefaultTransport
+       }
+
+       return &Client{
+               url:         cfg.URL,
+               username:    cfg.Username,
+               password:    cfg.Password,
+               graphspaces: cfg.GraphSpace,
+               graph:       cfg.Graph,
+               transport:   cfg.Transport,
+               logger:      cfg.Logger,
+       }
+}
+
+// Perform executes the request and returns a response or error.
+//
+func (c *Client) Perform(req *http.Request) (*http.Response, error) {
+
+       u := c.url
+       c.setURL(u, req)
+       c.setUserAgent(req)
+       c.setHost(req)
+       c.setContentTypeJSON(req)
+       c.setGraph(req)
+       c.setGraphSpace(req)
+       c.setBodyGraphInfo(req)
+
+       if _, ok := req.Header["Authorization"]; !ok {
+               c.setBasicAuth(u, req)
+       }
+
+       fmt.Println(req.Header)
+       var dupReqBody *bytes.Buffer
+       if c.logger != nil && c.logger.RequestBodyEnabled() {
+               if req.Body != nil && req.Body != http.NoBody {
+                       dupReqBody = bytes.NewBuffer(make([]byte, 0, 
int(req.ContentLength)))
+                       dupReqBody.ReadFrom(req.Body)
+                       req.Body = 
ioutil.NopCloser(bytes.NewBuffer(dupReqBody.Bytes()))
+               }
+       }
+       start := time.Now().UTC()
+       res, err := c.transport.RoundTrip(req)
+       dur := time.Since(start)
+       if c.logger != nil {

Review Comment:
   reduce if nesting



##########
hugegraph-client-go/hgapi/hgapi.go:
##########
@@ -0,0 +1,45 @@
+package hgapi
+
+import (
+       "net/http"
+       "strconv"
+       "time"
+
+       "hugegraph.apache.org/client-go/internal/version"
+)
+
+// VERSION returns the package version as a string.
+//
+const VERSION = version.Client
+
+// Transport defines the interface for an API client.
+//
+type Transport interface {
+       Perform(*http.Request) (*http.Response, error)
+}
+
+// BoolPtr returns a pointer to v.
+//
+// It is used as a convenience function for converting a bool value
+// into a pointer when passing the value to a function or struct field
+// which expects a pointer.
+//
+func BoolPtr(v bool) *bool { return &v }
+
+// IntPtr returns a pointer to v.
+//
+// It is used as a convenience function for converting an int value
+// into a pointer when passing the value to a function or struct field
+// which expects a pointer.
+//
+func IntPtr(v int) *int { return &v }

Review Comment:
   maybe boolPtr and IntPtr are unnecessary



##########
hugegraph-client-go/hgtransport/hgtransport.go:
##########
@@ -0,0 +1,246 @@
+package hgtransport
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "regexp"
+       "runtime"
+       "strings"
+       "time"
+
+       "hugegraph.apache.org/client-go/internal/version"
+)
+
+// Version returns the package version as a string.
+//
+const Version = version.Client
+
+var (
+       userAgent   string
+       reGoVersion = regexp.MustCompile(`go(\d+\.\d+\..+)`)
+)
+
+func init() {
+       userAgent = initUserAgent()
+}
+
+// Interface defines the interface for HTTP client.
+//
+type Interface interface {
+       Perform(*http.Request) (*http.Response, error)
+}
+
+// Config represents the configuration of HTTP client.
+//
+type Config struct {
+       URL        *url.URL
+       Username   string
+       Password   string
+       GraphSpace string
+       Graph      string
+
+       Transport http.RoundTripper
+       Logger    Logger
+}
+
+// Client represents the HTTP client.
+//
+type Client struct {
+       url         *url.URL
+       username    string
+       password    string
+       graphspaces string
+       graph       string
+
+       transport http.RoundTripper
+       logger    Logger
+}
+
+// New creates new HTTP client.
+//
+// http.DefaultTransport will be used if no transport is passed in the 
configuration.
+//
+func New(cfg Config) *Client {
+       if cfg.Transport == nil {
+               cfg.Transport = http.DefaultTransport
+       }
+
+       return &Client{
+               url:         cfg.URL,
+               username:    cfg.Username,
+               password:    cfg.Password,
+               graphspaces: cfg.GraphSpace,
+               graph:       cfg.Graph,
+               transport:   cfg.Transport,
+               logger:      cfg.Logger,
+       }
+}
+
+// Perform executes the request and returns a response or error.
+//
+func (c *Client) Perform(req *http.Request) (*http.Response, error) {
+
+       u := c.url
+       c.setURL(u, req)
+       c.setUserAgent(req)
+       c.setHost(req)
+       c.setContentTypeJSON(req)
+       c.setGraph(req)
+       c.setGraphSpace(req)
+       c.setBodyGraphInfo(req)
+
+       if _, ok := req.Header["Authorization"]; !ok {
+               c.setBasicAuth(u, req)
+       }
+
+       fmt.Println(req.Header)
+       var dupReqBody *bytes.Buffer
+       if c.logger != nil && c.logger.RequestBodyEnabled() {
+               if req.Body != nil && req.Body != http.NoBody {
+                       dupReqBody = bytes.NewBuffer(make([]byte, 0, 
int(req.ContentLength)))
+                       dupReqBody.ReadFrom(req.Body)
+                       req.Body = 
ioutil.NopCloser(bytes.NewBuffer(dupReqBody.Bytes()))
+               }
+       }
+       start := time.Now().UTC()
+       res, err := c.transport.RoundTrip(req)
+       dur := time.Since(start)
+       if c.logger != nil {
+               var dupRes http.Response
+               if res != nil {
+                       dupRes = *res
+               }
+               if c.logger.RequestBodyEnabled() {
+                       if req.Body != nil && req.Body != http.NoBody {
+                               req.Body = ioutil.NopCloser(dupReqBody)
+                       }
+               }
+               if c.logger.ResponseBodyEnabled() {
+                       if res != nil && res.Body != nil && res.Body != 
http.NoBody {
+                               b1, b2, _ := duplicateBody(res.Body)
+                               dupRes.Body = b1
+                               res.Body = b2
+                       }
+               }
+               c.logger.LogRoundTrip(req, &dupRes, err, start, dur) // 
errcheck exclude
+       }
+
+       // TODO(karmi): Wrap error
+       return res, err
+}
+
+func (c *Client) setURL(u *url.URL, req *http.Request) *http.Request {
+       req.URL.Scheme = u.Scheme
+       req.URL.Host = u.Host
+
+       if u.Path != "" {
+               var b strings.Builder
+               b.Grow(len(u.Path) + len(req.URL.Path))
+               b.WriteString(u.Path)
+               b.WriteString(req.URL.Path)
+               req.URL.Path = b.String()
+       }
+
+       return req
+}
+
+func (c *Client) setBasicAuth(u *url.URL, req *http.Request) *http.Request {
+       if u.User != nil {
+               password, _ := u.User.Password()
+               req.SetBasicAuth(u.User.Username(), password)
+               return req
+       }
+
+       if c.username != "" && c.password != "" {
+               req.SetBasicAuth(c.username, c.password)
+               return req
+       }
+
+       return req
+}
+
+func (c *Client) setUserAgent(req *http.Request) *http.Request {
+       req.Header.Set("User-Agent", userAgent)
+       return req
+}
+
+func (c *Client) setHost(req *http.Request) *http.Request {
+       req.Header.Set("Host", req.URL.Host)
+       return req
+}
+
+func (c *Client) setContentTypeJSON(req *http.Request) *http.Request {
+       req.Header.Set("Content-Type", "application/json")
+       return req
+}
+
+func (c *Client) setGraph(req *http.Request) *http.Request {
+       req.URL.RawQuery = strings.ReplaceAll(req.URL.RawQuery, 
url.QueryEscape("${GRAPH_NAME}"), c.graph)
+       req.URL.Path = strings.ReplaceAll(req.URL.Path, "${GRAPH_NAME}", 
c.graph)
+       return req
+}
+
+func (c *Client) setGraphSpace(req *http.Request) *http.Request {
+       req.URL.RawQuery = strings.ReplaceAll(req.URL.RawQuery, 
url.QueryEscape("${GRAPH_SPACE_NAME}"), c.graphspaces)
+       req.URL.Path = strings.ReplaceAll(req.URL.Path, "${GRAPH_SPACE_NAME}", 
c.graphspaces)
+       return req
+}
+
+func (c *Client) setBodyGraphInfo(req *http.Request) *http.Request {
+       //
+       if req.Body == nil {
+               return req
+       }
+       body, err := ioutil.ReadAll(req.Body)
+       if err != nil {
+               return req
+       }
+       // 关闭 r.Body,因为我们已经读取了全部内容
+       req.Body.Close()
+       // 将字节切片转换成字符串
+       bodyStr := string(body)
+
+       // 是否需要替换
+       if strings.Contains(bodyStr, 
`"graph":"${GRAPH_SPACE_NAME}-${GRAPH_NAME}"`) {

Review Comment:
   Why replace the body here instead of setting it when the request body is 
constructed?



##########
hugegraph-client-go/hgapi/hgapi.go:
##########
@@ -0,0 +1,45 @@
+package hgapi
+
+import (
+       "net/http"
+       "strconv"
+       "time"
+
+       "hugegraph.apache.org/client-go/internal/version"
+)
+
+// VERSION returns the package version as a string.
+//
+const VERSION = version.Client
+
+// Transport defines the interface for an API client.
+//
+type Transport interface {
+       Perform(*http.Request) (*http.Response, error)
+}
+
+// BoolPtr returns a pointer to v.
+//
+// It is used as a convenience function for converting a bool value
+// into a pointer when passing the value to a function or struct field
+// which expects a pointer.
+//
+func BoolPtr(v bool) *bool { return &v }

Review Comment:
   can we direct use &v replace BoolPtr?



##########
hugegraph-client-go/README.en.md:
##########
@@ -0,0 +1,36 @@
+# hugegraph
+
+#### Description
+基于Go语言的hugegraph client SDK工具

Review Comment:
   english description prefer



##########
hugegraph-client-go/Makefile:
##########
@@ -0,0 +1,58 @@
+# init project path
+HOMEDIR := $(shell pwd)
+OUTDIR  := $(HOMEDIR)/output
+
+# 设置编译时所需要的 go 环境
+export GOENV = $(HOMEDIR)/go.env
+
+GO      := go
+GOMOD   := $(GO) mod
+GOBUILD := $(GO) build
+GOTEST  := $(GO) test -race -timeout 30s -gcflags="-N -l"
+GOPKGS  := $$($(GO) list ./...| grep -vE "vendor")
+
+# test cover files
+COVPROF := $(HOMEDIR)/covprof.out  # coverage profile
+COVFUNC := $(HOMEDIR)/covfunc.txt  # coverage profile information for each 
function
+COVHTML := $(HOMEDIR)/covhtml.html # HTML representation of coverage profile
+
+# make, make all
+all: prepare compile package
+
+set-env:
+       $(GO) env 
+
+
+#make prepare, download dependencies
+prepare: gomod
+
+gomod: set-env
+       $(GOMOD) download -x || $(GOMOD) download -x
+
+#make compile
+compile: build
+
+build:
+       $(GOBUILD) -o $(HOMEDIR)/go-hugegraph
+
+# make test, test your code
+test: prepare test-case
+test-case:
+       $(GOTEST) -v -cover $(GOPKGS)
+
+# make package
+package: package-bin
+package-bin:
+       rm -rf $(OUTDIR)
+       mkdir -p $(OUTDIR)
+       mv go-hugegraph  $(OUTDIR)/
+
+# make clean
+clean:
+       $(GO) clean
+       rm -rf $(OUTDIR)
+       rm -rf $(HOMEDIR)/go-hugegraph
+       rm -rf $(GOPATH)/pkg/darwin_amd64
+
+# avoid filename conflict and speed up build
+.PHONY: all prepare compile test package clean build 

Review Comment:
   gofmt missed



##########
hugegraph-client-go/Makefile:
##########
@@ -0,0 +1,58 @@
+# init project path
+HOMEDIR := $(shell pwd)
+OUTDIR  := $(HOMEDIR)/output
+
+# 设置编译时所需要的 go 环境
+export GOENV = $(HOMEDIR)/go.env
+
+GO      := go
+GOMOD   := $(GO) mod
+GOBUILD := $(GO) build
+GOTEST  := $(GO) test -race -timeout 30s -gcflags="-N -l"
+GOPKGS  := $$($(GO) list ./...| grep -vE "vendor")
+
+# test cover files
+COVPROF := $(HOMEDIR)/covprof.out  # coverage profile
+COVFUNC := $(HOMEDIR)/covfunc.txt  # coverage profile information for each 
function
+COVHTML := $(HOMEDIR)/covhtml.html # HTML representation of coverage profile
+
+# make, make all
+all: prepare compile package
+
+set-env:
+       $(GO) env 
+
+
+#make prepare, download dependencies
+prepare: gomod
+
+gomod: set-env

Review Comment:
   why not GO111MODULE=on go mod tidy



##########
hugegraph-client-go/hgtransport/logger.go:
##########
@@ -0,0 +1,388 @@
+package hgtransport
+
+import (
+       "bufio"
+       "bytes"
+       "encoding/json"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "strconv"
+       "strings"
+       "time"
+)
+
+// Logger defines an interface for logging request and response.
+//
+type Logger interface {
+       // LogRoundTrip should not modify the request or response, except for 
consuming and closing the body.
+       // Implementations have to check for nil values in request and response.
+       LogRoundTrip(*http.Request, *http.Response, error, time.Time, 
time.Duration) error
+       // RequestBodyEnabled makes the client pass a copy of request body to 
the logger.
+       RequestBodyEnabled() bool
+       // ResponseBodyEnabled makes the client pass a copy of response body to 
the logger.
+       ResponseBodyEnabled() bool
+}
+
+// TextLogger prints the log message in plain text.
+//
+type TextLogger struct {
+       Output             io.Writer
+       EnableRequestBody  bool
+       EnableResponseBody bool
+}
+
+// ColorLogger prints the log message in a terminal-optimized plain text.
+//
+type ColorLogger struct {
+       Output             io.Writer
+       EnableRequestBody  bool
+       EnableResponseBody bool
+}
+
+// CurlLogger prints the log message as a runnable curl command.
+//
+type CurlLogger struct {
+       Output             io.Writer
+       EnableRequestBody  bool
+       EnableResponseBody bool
+}
+
+// JSONLogger prints the log message as JSON.
+//
+type JSONLogger struct {
+       Output             io.Writer
+       EnableRequestBody  bool
+       EnableResponseBody bool
+}
+
+// LogRoundTrip prints the information about request and response.
+//
+func (l *TextLogger) LogRoundTrip(req *http.Request, res *http.Response, err 
error, start time.Time, dur time.Duration) error {
+       fmt.Fprintf(l.Output, "%s %s %s [status:%d request:%s]\n",

Review Comment:
   why there need custom logger? why no use other logger framework?



##########
hugegraph-client-go/hgtransport/hgtransport.go:
##########
@@ -0,0 +1,246 @@
+package hgtransport
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "regexp"
+       "runtime"
+       "strings"
+       "time"
+
+       "hugegraph.apache.org/client-go/internal/version"
+)
+
+// Version returns the package version as a string.
+//
+const Version = version.Client
+
+var (
+       userAgent   string
+       reGoVersion = regexp.MustCompile(`go(\d+\.\d+\..+)`)
+)
+
+func init() {
+       userAgent = initUserAgent()
+}
+
+// Interface defines the interface for HTTP client.
+//
+type Interface interface {
+       Perform(*http.Request) (*http.Response, error)
+}
+
+// Config represents the configuration of HTTP client.
+//
+type Config struct {
+       URL        *url.URL
+       Username   string
+       Password   string
+       GraphSpace string
+       Graph      string
+
+       Transport http.RoundTripper
+       Logger    Logger
+}
+
+// Client represents the HTTP client.
+//
+type Client struct {
+       url         *url.URL
+       username    string
+       password    string
+       graphspaces string
+       graph       string
+
+       transport http.RoundTripper
+       logger    Logger
+}
+
+// New creates new HTTP client.
+//
+// http.DefaultTransport will be used if no transport is passed in the 
configuration.
+//
+func New(cfg Config) *Client {
+       if cfg.Transport == nil {
+               cfg.Transport = http.DefaultTransport
+       }
+
+       return &Client{
+               url:         cfg.URL,
+               username:    cfg.Username,
+               password:    cfg.Password,
+               graphspaces: cfg.GraphSpace,
+               graph:       cfg.Graph,
+               transport:   cfg.Transport,
+               logger:      cfg.Logger,
+       }
+}
+
+// Perform executes the request and returns a response or error.
+//
+func (c *Client) Perform(req *http.Request) (*http.Response, error) {
+
+       u := c.url
+       c.setURL(u, req)
+       c.setUserAgent(req)
+       c.setHost(req)
+       c.setContentTypeJSON(req)
+       c.setGraph(req)
+       c.setGraphSpace(req)
+       c.setBodyGraphInfo(req)
+
+       if _, ok := req.Header["Authorization"]; !ok {
+               c.setBasicAuth(u, req)
+       }
+
+       fmt.Println(req.Header)
+       var dupReqBody *bytes.Buffer
+       if c.logger != nil && c.logger.RequestBodyEnabled() {
+               if req.Body != nil && req.Body != http.NoBody {
+                       dupReqBody = bytes.NewBuffer(make([]byte, 0, 
int(req.ContentLength)))
+                       dupReqBody.ReadFrom(req.Body)
+                       req.Body = 
ioutil.NopCloser(bytes.NewBuffer(dupReqBody.Bytes()))
+               }
+       }
+       start := time.Now().UTC()
+       res, err := c.transport.RoundTrip(req)
+       dur := time.Since(start)
+       if c.logger != nil {
+               var dupRes http.Response
+               if res != nil {
+                       dupRes = *res
+               }
+               if c.logger.RequestBodyEnabled() {
+                       if req.Body != nil && req.Body != http.NoBody {
+                               req.Body = ioutil.NopCloser(dupReqBody)
+                       }
+               }
+               if c.logger.ResponseBodyEnabled() {
+                       if res != nil && res.Body != nil && res.Body != 
http.NoBody {
+                               b1, b2, _ := duplicateBody(res.Body)
+                               dupRes.Body = b1
+                               res.Body = b2
+                       }
+               }
+               c.logger.LogRoundTrip(req, &dupRes, err, start, dur) // 
errcheck exclude
+       }
+
+       // TODO(karmi): Wrap error
+       return res, err
+}
+
+func (c *Client) setURL(u *url.URL, req *http.Request) *http.Request {
+       req.URL.Scheme = u.Scheme
+       req.URL.Host = u.Host
+
+       if u.Path != "" {
+               var b strings.Builder
+               b.Grow(len(u.Path) + len(req.URL.Path))
+               b.WriteString(u.Path)
+               b.WriteString(req.URL.Path)
+               req.URL.Path = b.String()
+       }
+
+       return req
+}
+
+func (c *Client) setBasicAuth(u *url.URL, req *http.Request) *http.Request {
+       if u.User != nil {
+               password, _ := u.User.Password()
+               req.SetBasicAuth(u.User.Username(), password)
+               return req
+       }
+
+       if c.username != "" && c.password != "" {
+               req.SetBasicAuth(c.username, c.password)
+               return req
+       }
+
+       return req
+}
+
+func (c *Client) setUserAgent(req *http.Request) *http.Request {
+       req.Header.Set("User-Agent", userAgent)
+       return req
+}
+
+func (c *Client) setHost(req *http.Request) *http.Request {
+       req.Header.Set("Host", req.URL.Host)
+       return req
+}
+
+func (c *Client) setContentTypeJSON(req *http.Request) *http.Request {
+       req.Header.Set("Content-Type", "application/json")
+       return req
+}
+
+func (c *Client) setGraph(req *http.Request) *http.Request {
+       req.URL.RawQuery = strings.ReplaceAll(req.URL.RawQuery, 
url.QueryEscape("${GRAPH_NAME}"), c.graph)
+       req.URL.Path = strings.ReplaceAll(req.URL.Path, "${GRAPH_NAME}", 
c.graph)
+       return req
+}
+
+func (c *Client) setGraphSpace(req *http.Request) *http.Request {
+       req.URL.RawQuery = strings.ReplaceAll(req.URL.RawQuery, 
url.QueryEscape("${GRAPH_SPACE_NAME}"), c.graphspaces)
+       req.URL.Path = strings.ReplaceAll(req.URL.Path, "${GRAPH_SPACE_NAME}", 
c.graphspaces)
+       return req
+}
+
+func (c *Client) setBodyGraphInfo(req *http.Request) *http.Request {
+       //
+       if req.Body == nil {
+               return req
+       }
+       body, err := ioutil.ReadAll(req.Body)
+       if err != nil {
+               return req
+       }
+       // 关闭 r.Body,因为我们已经读取了全部内容
+       req.Body.Close()
+       // 将字节切片转换成字符串
+       bodyStr := string(body)
+
+       // 是否需要替换
+       if strings.Contains(bodyStr, 
`"graph":"${GRAPH_SPACE_NAME}-${GRAPH_NAME}"`) {

Review Comment:
   Why replace the body here instead of setting it when the request body is 
constructed?



##########
hugegraph-client-go/hgtransport/hgtransport.go:
##########
@@ -0,0 +1,246 @@
+package hgtransport
+
+import (
+       "bytes"
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "regexp"
+       "runtime"
+       "strings"
+       "time"
+
+       "hugegraph.apache.org/client-go/internal/version"
+)
+
+// Version returns the package version as a string.
+//
+const Version = version.Client
+
+var (
+       userAgent   string
+       reGoVersion = regexp.MustCompile(`go(\d+\.\d+\..+)`)
+)
+
+func init() {
+       userAgent = initUserAgent()
+}
+
+// Interface defines the interface for HTTP client.
+//
+type Interface interface {
+       Perform(*http.Request) (*http.Response, error)
+}
+
+// Config represents the configuration of HTTP client.
+//
+type Config struct {
+       URL        *url.URL
+       Username   string
+       Password   string
+       GraphSpace string
+       Graph      string
+
+       Transport http.RoundTripper
+       Logger    Logger
+}
+
+// Client represents the HTTP client.
+//
+type Client struct {
+       url         *url.URL
+       username    string
+       password    string
+       graphspaces string
+       graph       string
+
+       transport http.RoundTripper
+       logger    Logger
+}
+
+// New creates new HTTP client.
+//
+// http.DefaultTransport will be used if no transport is passed in the 
configuration.
+//
+func New(cfg Config) *Client {
+       if cfg.Transport == nil {
+               cfg.Transport = http.DefaultTransport
+       }
+
+       return &Client{
+               url:         cfg.URL,
+               username:    cfg.Username,
+               password:    cfg.Password,
+               graphspaces: cfg.GraphSpace,
+               graph:       cfg.Graph,
+               transport:   cfg.Transport,
+               logger:      cfg.Logger,
+       }
+}
+
+// Perform executes the request and returns a response or error.
+//
+func (c *Client) Perform(req *http.Request) (*http.Response, error) {

Review Comment:
   This method is to forward the business request to the backend. The request 
parameter here is net.httprequest, so here it should be to call http directly. 
It is better not to have business processing. Authorization and monitoring can 
be viewed here, but it is best to modify the request body It is best to do it 
when constructing httpRequest
   
             



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to