From 80e0eae6b0731f71edc06a5b5ddb8fb9a7d685c4 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 19 Mar 2019 17:48:37 +0800 Subject: [PATCH] add TLSConfig support for ghttp.Server --- g/encoding/gjson/gjson.go | 5 ++++ g/net/ghttp/ghttp_client_request_client.go | 12 ++++++++-- g/net/ghttp/ghttp_server.go | 5 ++-- g/net/ghttp/ghttp_server_config.go | 28 ++++++++++++++++++---- g/net/ghttp/ghttp_server_graceful.go | 14 +++++++---- g/util/gconv/gconv.go | 9 +++---- geg/net/ghttp/server/https/https.go | 2 +- 7 files changed, 57 insertions(+), 18 deletions(-) diff --git a/g/encoding/gjson/gjson.go b/g/encoding/gjson/gjson.go index 7cbfef3ce..6e375d5d4 100644 --- a/g/encoding/gjson/gjson.go +++ b/g/encoding/gjson/gjson.go @@ -79,6 +79,11 @@ func NewUnsafe(value...interface{}) *Json { return New(nil, true) } +// 识别当前给定内容是否为JSON格式 +func Valid (v interface{}) bool { + return json.Valid(gconv.Bytes(v)) +} + // 编码go变量为json字符串,并返回json字符串指针 func Encode (v interface{}) ([]byte, error) { return json.Marshal(v) diff --git a/g/net/ghttp/ghttp_client_request_client.go b/g/net/ghttp/ghttp_client_request_client.go index 567bdc869..4b3854b23 100644 --- a/g/net/ghttp/ghttp_client_request_client.go +++ b/g/net/ghttp/ghttp_client_request_client.go @@ -9,6 +9,7 @@ package ghttp import ( + "encoding/json" "github.com/gogf/gf/g/text/gregex" "time" "bytes" @@ -117,6 +118,7 @@ func (c *Client) Post(url string, data...string) (*ClientResponse, error) { } req := (*http.Request)(nil) if strings.Contains(param, "@file:") { + // 文件上传 buffer := new(bytes.Buffer) writer := multipart.NewWriter(buffer) for _, item := range strings.Split(param, "&") { @@ -150,11 +152,17 @@ func (c *Client) Post(url string, data...string) (*ClientResponse, error) { req.Header.Set("Content-Type", writer.FormDataContentType()) } } else { - if r, err := http.NewRequest("POST", url, bytes.NewReader([]byte(param))); err != nil { + // 识别提交数据格式 + paramBytes := []byte(param) + if r, err := http.NewRequest("POST", url, bytes.NewReader(paramBytes)); err != nil { return nil, err } else { req = r - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + if json.Valid(paramBytes) { + req.Header.Set("Content-Type", "application/json") + } else { + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } } } // 自定义header diff --git a/g/net/ghttp/ghttp_server.go b/g/net/ghttp/ghttp_server.go index b842d5df1..400e3afc6 100644 --- a/g/net/ghttp/ghttp_server.go +++ b/g/net/ghttp/ghttp_server.go @@ -398,7 +398,8 @@ func Wait() { // 开启底层Web Server执行 func (s *Server) startServer(fdMap listenerFdMap) { var httpsEnabled bool - if len(s.config.HTTPSCertPath) > 0 && len(s.config.HTTPSKeyPath) > 0 { + // 判断是否启用HTTPS + if len(s.config.TLSConfig.Certificates) > 0 || (len(s.config.HTTPSCertPath) > 0 && len(s.config.HTTPSKeyPath) > 0) { // ================ // HTTPS // ================ @@ -479,7 +480,7 @@ func (s *Server) startServer(fdMap listenerFdMap) { s.serverCount.Add(1) err := (error)(nil) if server.isHttps { - err = server.ListenAndServeTLS(s.config.HTTPSCertPath, s.config.HTTPSKeyPath) + err = server.ListenAndServeTLS(s.config.HTTPSCertPath, s.config.HTTPSKeyPath, &s.config.TLSConfig) } else { err = server.ListenAndServe() } diff --git a/g/net/ghttp/ghttp_server_config.go b/g/net/ghttp/ghttp_server_config.go index f73cfe606..73b4448a3 100644 --- a/g/net/ghttp/ghttp_server_config.go +++ b/g/net/ghttp/ghttp_server_config.go @@ -7,6 +7,7 @@ package ghttp import ( + "crypto/tls" "fmt" "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/os/glog" @@ -44,6 +45,7 @@ type ServerConfig struct { WriteTimeout time.Duration // 写入超时 IdleTimeout time.Duration // 等待超时 MaxHeaderBytes int // 最大的header长度 + TLSConfig tls.Config // 静态文件配置 IndexFiles []string // 默认访问的文件列表 @@ -191,28 +193,46 @@ func (s *Server)SetHTTPSPort(port...int) { } } -// 开启HTTPS支持,但是必须提供Cert和Key文件 -func (s *Server)EnableHTTPS(certFile, keyFile string) { +// 开启HTTPS支持,但是必须提供Cert和Key文件,tlsConfig为可选项 +func (s *Server)EnableHTTPS(certFile, keyFile string, tlsConfig...tls.Config) { if s.Status() == SERVER_STATUS_RUNNING { glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR) return } certFileRealPath := gfile.RealPath(certFile) if certFileRealPath == "" { - certFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + certFileRealPath) + certFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + certFile) + if certFileRealPath == "" { + certFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + certFile) + } } if certFileRealPath == "" { glog.Fatal(fmt.Sprintf(`[ghttp] EnableHTTPS failed: certFile "%s" does not exist`, certFile)) } keyFileRealPath := gfile.RealPath(keyFile) if keyFileRealPath == "" { - keyFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + keyFileRealPath) + keyFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + keyFile) + if keyFileRealPath == "" { + keyFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + keyFile) + } } if keyFileRealPath == "" { glog.Fatal(fmt.Sprintf(`[ghttp] EnableHTTPS failed: keyFile "%s" does not exist`, keyFile)) } s.config.HTTPSCertPath = certFileRealPath s.config.HTTPSKeyPath = keyFileRealPath + if len(tlsConfig) > 0 { + s.config.TLSConfig = tlsConfig[0] + } +} + +// 设置TLS配置对象 +func (s *Server)SetTLSConfig(tlsConfig tls.Config) { + if s.Status() == SERVER_STATUS_RUNNING { + glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR) + return + } + s.config.TLSConfig = tlsConfig } // 设置http server参数 - ReadTimeout diff --git a/g/net/ghttp/ghttp_server_graceful.go b/g/net/ghttp/ghttp_server_graceful.go index d7444eb28..5b8fa01ba 100644 --- a/g/net/ghttp/ghttp_server_graceful.go +++ b/g/net/ghttp/ghttp_server_graceful.go @@ -84,18 +84,22 @@ func (s *gracefulServer) setFd(fd int) { } // 执行HTTPS监听 -func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string) error { +func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string, tlsConfig...*tls.Config) error { addr := s.httpServer.Addr - config := &tls.Config{} - if s.httpServer.TLSConfig != nil { + config := (*tls.Config)(nil) + if len(tlsConfig) > 0 { + config = tlsConfig[0] + } else if s.httpServer.TLSConfig != nil { *config = *s.httpServer.TLSConfig } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } err := error(nil) - config.Certificates = make([]tls.Certificate, 1) - config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) + if len(config.Certificates) == 0 { + config.Certificates = make([]tls.Certificate, 1) + config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) + } if err != nil { return errors.New(fmt.Sprintf(`open cert file "%s","%s" failed: %s`, certFile, keyFile, err.Error())) } diff --git a/g/util/gconv/gconv.go b/g/util/gconv/gconv.go index f5ab6f2b0..f3a95c205 100644 --- a/g/util/gconv/gconv.go +++ b/g/util/gconv/gconv.go @@ -79,10 +79,11 @@ func Bytes(i interface{}) []byte { if i == nil { return nil } - if r, ok := i.([]byte); ok { - return r - } else { - return gbinary.Encode(i) + switch value := i.(type) { + case string: return []byte(value) + case []byte: return value + default: + return gbinary.Encode(i) } } diff --git a/geg/net/ghttp/server/https/https.go b/geg/net/ghttp/server/https/https.go index 09cff5661..be41c88b7 100644 --- a/geg/net/ghttp/server/https/https.go +++ b/geg/net/ghttp/server/https/https.go @@ -9,7 +9,7 @@ func main() { s.BindHandler("/", func(r *ghttp.Request){ r.Response.Writeln("来自于HTTPS的:哈喽世界!") }) - s.EnableHTTPS("/home/john/temp/server.crt", "/home/john/temp/server.key") + s.EnableHTTPS("./server.crt", "./server.key") s.SetPort(8199) s.Run() } \ No newline at end of file