diff --git a/http/drivers/gout/client.go b/http/drivers/gout/client.go index a7d4598..cd049ef 100644 --- a/http/drivers/gout/client.go +++ b/http/drivers/gout/client.go @@ -2,7 +2,10 @@ package gout import ( "bytes" + "crypto/tls" + "crypto/x509" "encoding/json" + "errors" "fmt" "github.com/ArtisanCloud/PowerLibs/http/contract" "github.com/ArtisanCloud/PowerLibs/http/response" @@ -14,6 +17,7 @@ import ( "io/ioutil" "net/http" "net/url" + "os" "path" ) @@ -51,7 +55,7 @@ func (client *Client) SendAsync(request contract.RequestInterface, options *obje func (client *Client) PrepareRequest(method string, uri string, options *object.HashMap, outBody interface{}) ( df *dataflow.DataFlow, queries *object.StringMap, headers interface{}, body interface{}, - version string, debug bool) { + version string, debug bool, err error) { (*options)[OPTION_SYNCHRONOUS] = true options = client.prepareDefaults(options) @@ -80,9 +84,18 @@ func (client *Client) PrepareRequest(method string, uri string, options *object. // load middlewares stack if (*options)["handler"] != nil { middlewares := (*options)["handler"].([]interface{}) - client.useMiddleware(df, middlewares, outBody) + err = client.useMiddleware(df, middlewares, outBody) + if err != nil { + return df, queries, headers, body, version, debug, err + } } + // apply handle option + //df, err = ApplyHandleOptions(df, options) + //if err != nil { + // return df, queries, headers, body, version, debug, err + //} + // append query queries = &object.StringMap{} if (*options)["query"] != nil { @@ -100,12 +113,16 @@ func (client *Client) PrepareRequest(method string, uri string, options *object. fmt.Println("wx debug mode open") } - return df, queries, headers, body, version, debug + return df, queries, headers, body, version, debug, err } func (client *Client) Request(method string, uri string, options *object.HashMap, returnRaw bool, outHeader interface{}, outBody interface{}) (contract.ResponseInterface, error) { - df, queries, headers, body, _, debug := client.PrepareRequest(method, uri, options, outBody) + df, queries, headers, body, _, debug, err := client.PrepareRequest(method, uri, options, outBody) + + if err != nil { + return nil, err + } df = client.applyOptions(df, options) @@ -135,7 +152,7 @@ func (client *Client) Request(method string, uri string, options *object.HashMap } } - err := df.Do() + err = df.Do() if err != nil { fmt.Printf("http request error:%s \n", err.Error()) return nil, err @@ -165,7 +182,7 @@ func (client *Client) GetHttpResponseFrom(returnCode int, outHeader interface{}, } // copy header - mapHeader, _ := object.StructToStringMap(outHeader,"") + mapHeader, _ := object.StructToStringMap(outHeader) for key, header := range *mapHeader { rs.Header.Add(key, header) } @@ -369,3 +386,70 @@ func (client *Client) handleRetryMiddleware(df *dataflow.DataFlow, retryMiddlewa return df, nil } + +func ApplyHandleOptions(df *dataflow.DataFlow, options *object.HashMap) (*dataflow.DataFlow, error) { + + var err error + var cert, sslKey string + if (*options)["cert"] != nil { + cert = (*options)["cert"].(string) + + if _, err = os.Stat(cert); os.IsNotExist(err) { + err = errors.New("SSL certificate not found:" + cert) + return df, err + } + } + if (*options)["ssl_key"] != nil { + sslKey = (*options)["ssl_key"].(string) + + if _, err = os.Stat(cert); os.IsNotExist(err) { + err = errors.New("SSL certificate not found:" + cert) + return df, err + } + } + if cert == "" || sslKey == "" { + return df, nil + } + + tlsConfig, err := NewTLSConfig(cert, sslKey, "") + if err != nil { + return df, err + } + tr := &http.Transport{TLSClientConfig: tlsConfig} + + df.Client().Transport = tr + + return df, err +} + +func NewTLSConfig(clientCertFile string, clientKeyFile string, caCertFile string) (*tls.Config, error) { + + // Load client cert + tlsCert, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile) + if err != nil { + return nil, err + } + + tlsConfig := tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + InsecureSkipVerify: false, + ClientAuth: tls.RequireAndVerifyClientCert, + MinVersion: tls.VersionTLS12, + } + + // Load CA cert + if caCertFile != "" { + certBytes, err := ioutil.ReadFile(caCertFile) + if err != nil { + return nil, err + } + caCertPool := x509.NewCertPool() + if ok := caCertPool.AppendCertsFromPEM(certBytes); !ok { + return nil, errors.New("Unable to load caCert") + } + tlsConfig.RootCAs = caCertPool + tlsConfig.ClientCAs = caCertPool + } + + return &tlsConfig, nil +} diff --git a/http/request/request.go b/http/request/request.go index f1a54c3..f090e5c 100644 --- a/http/request/request.go +++ b/http/request/request.go @@ -28,8 +28,8 @@ func NewHttpRequest(config *object.HashMap) *HttpRequest { if (*config)["cert_path"] != nil && (*config)["key_path"] != nil { certPath := (*config)["cert_path"].(string) keyPath := (*config)["key_path"].(string) - if certPath!="" && keyPath!=""{ - var err error + if certPath != "" && keyPath != "" { + var err error httpClient, err = NewTLSHttpClient(certPath, keyPath) if err != nil { log.Fatalln("New TLS http client error:", err) @@ -103,7 +103,10 @@ func NewTLSHttpClient(certFile string, keyFile string) (httpClient *http.Client, return nil, err } tlsConfig := &tls.Config{ - Certificates: []tls.Certificate{cert}, + Certificates: []tls.Certificate{cert}, + InsecureSkipVerify: false, + ClientAuth: tls.RequireAndVerifyClientCert, + MinVersion: tls.VersionTLS12, } httpClient = &http.Client{ diff --git a/logger/app.go b/logger/app.go index e6ee34e..86526a4 100644 --- a/logger/app.go +++ b/logger/app.go @@ -4,6 +4,7 @@ import ( "github.com/ArtisanCloud/PowerLibs/logger/contract" "github.com/ArtisanCloud/PowerLibs/logger/drivers/zap" "github.com/ArtisanCloud/PowerLibs/object" + "os" ) type Logger struct { @@ -62,3 +63,28 @@ func (log *Logger) PanicF(format string, args ...interface{}) { func (log *Logger) FatalF(format string, args ...interface{}) { log.Driver.FatalF(format, args) } + + + +func InitLogPath(path string, files ...string) (err error) { + if _, err = os.Stat(path); os.IsNotExist(err) { + err = os.MkdirAll(path, os.ModePerm) + if err != nil { + return err + } + } else if os.IsPermission(err) { + return err + } + + for _, fileName := range files { + if _, err = os.Stat(fileName); os.IsNotExist(err) { + _, err = os.Create(fileName) + if err != nil { + return err + } + } + } + + return err + +} \ No newline at end of file diff --git a/logger/drivers/zap/log.go b/logger/drivers/zap/log.go index 186d593..5953708 100644 --- a/logger/drivers/zap/log.go +++ b/logger/drivers/zap/log.go @@ -71,39 +71,39 @@ func newZapLogger(config *object.HashMap) (logger *zap.Logger, err error) { } func (log *Logger) Debug(msg string, v ...interface{}) { - log.sugar.Debugw(msg, v) + log.sugar.Debugw(msg, v...) } func (log *Logger) Info(msg string, v ...interface{}) { - log.sugar.Infow(msg, v) + log.sugar.Infow(msg, v...) } func (log *Logger) Warn(msg string, v ...interface{}) { - log.sugar.Warnw(msg, v) + log.sugar.Warnw(msg, v...) } func (log *Logger) Error(msg string, v ...interface{}) { - log.sugar.Errorw(msg, v) + log.sugar.Errorw(msg, v...) } func (log *Logger) Panic(msg string, v ...interface{}) { - log.sugar.Panicw(msg, v) + log.sugar.Panicw(msg, v...) } func (log *Logger) Fatal(msg string, v ...interface{}) { - log.sugar.Fatalw(msg, v) + log.sugar.Fatalw(msg, v...) } func (log *Logger) DebugF(format string, args ...interface{}) { - log.sugar.Debugf(format, args) + log.sugar.Debugf(format, args...) } func (log *Logger) InfoF(format string, args ...interface{}) { - log.sugar.Infof(format, args) + log.sugar.Infof(format, args...) } func (log *Logger) WarnF(format string, args ...interface{}) { - log.sugar.Warnf(format, args) + log.sugar.Warnf(format, args...) } func (log *Logger) ErrorF(format string, args ...interface{}) { - log.sugar.Errorf(format, args) + log.sugar.Errorf(format, args...) } func (log *Logger) PanicF(format string, args ...interface{}) { - log.sugar.Panicf(format, args) + log.sugar.Panicf(format, args...) } func (log *Logger) FatalF(format string, args ...interface{}) { - log.sugar.Fatalf(format, args) + log.sugar.Fatalf(format, args...) } diff --git a/logger/drivers/zap/log_test.go b/logger/drivers/zap/log_test.go new file mode 100644 index 0000000..a96f888 --- /dev/null +++ b/logger/drivers/zap/log_test.go @@ -0,0 +1,56 @@ +package zap + +import ( + "github.com/ArtisanCloud/PowerLibs/object" + "net/http" + "os" + "testing" +) + +var strArtisanCloudPath = "/var/log/ArtisanCloud/PowerLibs" +var strOutputPath = strArtisanCloudPath + "/output.log" +var strErrorPath = strArtisanCloudPath + "/errors.log" + +func init() { + err := initLogPath(strArtisanCloudPath, strOutputPath, strErrorPath) + if err != nil { + panic(err) + } +} + +func Test_Log_Info(t *testing.T) { + logger, err := NewLogger(&object.HashMap{ + "env": "test", + "outputPath": strOutputPath, + "errorPath": strErrorPath, + }) + if err != nil { + t.Error(err) + } + + logger.Info("test info", "response", &http.Response{}) + +} + +func initLogPath(path string, files ...string) (err error) { + if _, err = os.Stat(path); os.IsNotExist(err) { + err = os.MkdirAll(path, os.ModePerm) + if err != nil { + return err + } + } else if os.IsPermission(err) { + return err + } + + for _, fileName := range files { + if _, err = os.Stat(fileName); os.IsNotExist(err) { + _, err = os.Create(fileName) + if err != nil { + return err + } + } + } + + return err + +} diff --git a/object/hashMap.go b/object/hashMap.go index dd473bf..5f90166 100644 --- a/object/hashMap.go +++ b/object/hashMap.go @@ -2,12 +2,12 @@ package object import ( "encoding/json" + "fmt" "reflect" ) type HashMap map[string]interface{} - // ------------------------------- Merge -------------------------------------------- func MergeHashMap(toMap *HashMap, subMaps ...*HashMap) *HashMap { if toMap == nil { @@ -23,9 +23,49 @@ func MergeHashMap(toMap *HashMap, subMaps ...*HashMap) *HashMap { return toMap } +// ------------------------------- Conversion --------------------------------------- + +func HashMapToStringMap(obj *HashMap) (newMap *StringMap, err error) { + newMap = &StringMap{} + + if obj == nil { + return newMap, err + } + + for k, v := range *obj { + (*newMap)[k] = fmt.Sprintf("%v", v) + } + + return newMap, err + +} + +func StructToHashMapWithTag(obj interface{}, tag string) (newMap *HashMap, err error) { + + newMap = &HashMap{} + + if obj == nil { + return newMap, err + } + + e := reflect.ValueOf(obj).Elem() + + for i := 0; i < e.NumField(); i++ { + field := e.Field(i).Interface() + + key := e.Type().Field(i).Name + if tag != "" { + key = e.Type().Field(i).Tag.Get(tag) + } + (*newMap)[key] = field + + } + + return newMap, err + +} -// ------------------------------- Conversion --------------------------------------- func StructToHashMap(obj interface{}) (newMap *HashMap, err error) { data, err := json.Marshal(obj) // Convert to a json string @@ -38,8 +78,6 @@ func StructToHashMap(obj interface{}) (newMap *HashMap, err error) { return } - - // ------------------------------- Search -------------------------------------------- func InHash(val interface{}, hash *HashMap) (exists bool, key string) { exists = false diff --git a/object/stringMap.go b/object/stringMap.go index 51298fb..b614ee4 100644 --- a/object/stringMap.go +++ b/object/stringMap.go @@ -2,6 +2,7 @@ package object import ( "bytes" + "encoding/json" "fmt" "reflect" "sort" @@ -35,7 +36,7 @@ func ConvertStringMapToString(m *StringMap, separate string) string { // ------------------------------- Conversion --------------------------------------- -func StructToStringMap(obj interface{}, tag string) (newMap *StringMap, err error) { +func StructToStringMapWithTag(obj interface{}, tag string) (newMap *StringMap, err error) { newMap = &StringMap{} @@ -62,6 +63,18 @@ func StructToStringMap(obj interface{}, tag string) (newMap *StringMap, err erro } +func StructToStringMap(obj interface{}) (newMap *StringMap, err error) { + data, err := json.Marshal(obj) // Convert to a json string + + if err != nil { + return + } + + newMap = &StringMap{} + err = json.Unmarshal(data, newMap) // Convert to a map + return +} + func GetJoinedWithKSort(params *StringMap) string { var strJoined string diff --git a/object/xml.go b/object/xml.go index e95f221..9f3a1f9 100644 --- a/object/xml.go +++ b/object/xml.go @@ -20,11 +20,22 @@ func Map2Xml(obj *HashMap) (strXML string) { switch v.(type) { case string: strXML = strXML + fmt.Sprintf("<%s>", k, v, k) + break case int: - strXML = strXML + fmt.Sprintf("<%s>", k, v, k) + case int8: + case int16: + case int32: + case int64: + strXML = strXML + fmt.Sprintf("<%s>%d", k, v, k) + break + case float32: + case float64: + strXML = strXML + fmt.Sprintf("<%s>%f", k, v, k) + break case interface{}: b, _ := json.Marshal(v) strXML = strXML + fmt.Sprintf("<%s>", k, string(b), k) + break } } return "" + strXML + ""