diff --git a/net/ghttp/ghttp_client_request.go b/net/ghttp/ghttp_client_request.go index 9df02cc90..eaf686334 100644 --- a/net/ghttp/ghttp_client_request.go +++ b/net/ghttp/ghttp_client_request.go @@ -36,124 +36,8 @@ func (c *Client) Put(url string, data ...interface{}) (*ClientResponse, error) { // Post sends request using HTTP method POST and returns the response object. // Note that the response object MUST be closed if it'll be never used. -// -// Note that it uses "multipart/form-data" as its Content-Type if it contains file uploading, -// else it uses "application/x-www-form-urlencoded". It also automatically detects the post -// content for JSON format, and for that it automatically sets the Content-Type as "application/json". -func (c *Client) Post(url string, data ...interface{}) (resp *ClientResponse, err error) { - if len(c.prefix) > 0 { - url = c.prefix + url - } - param := "" - if len(data) > 0 { - param = BuildParams(data[0]) - } - req := (*http.Request)(nil) - if strings.Contains(param, "@file:") { - // File uploading request. - buffer := new(bytes.Buffer) - writer := multipart.NewWriter(buffer) - for _, item := range strings.Split(param, "&") { - array := strings.Split(item, "=") - if len(array[1]) > 6 && strings.Compare(array[1][0:6], "@file:") == 0 { - path := array[1][6:] - if !gfile.Exists(path) { - return nil, errors.New(fmt.Sprintf(`"%s" does not exist`, path)) - } - if file, err := writer.CreateFormFile(array[0], path); err == nil { - if f, err := os.Open(path); err == nil { - defer f.Close() - if _, err = io.Copy(file, f); err != nil { - return nil, err - } - } else { - return nil, err - } - } else { - return nil, err - } - } else { - writer.WriteField(array[0], array[1]) - } - } - writer.Close() - if req, err = http.NewRequest("POST", url, buffer); err != nil { - return nil, err - } else { - req.Header.Set("Content-Type", writer.FormDataContentType()) - } - } else { - // Normal request. - paramBytes := []byte(param) - if req, err = http.NewRequest("POST", url, bytes.NewReader(paramBytes)); err != nil { - return nil, err - } else { - if v, ok := c.header["Content-Type"]; ok { - // Custom Content-Type. - req.Header.Set("Content-Type", v) - } else { - if json.Valid(paramBytes) { - // Auto detecting and setting the post content format: JSON. - req.Header.Set("Content-Type", "application/json") - } else if gregex.IsMatchString(`^[\w\[\]]+=.+`, param) { - // If the parameters passed like "name=value", it then uses form type. - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - } - } - } - } - // Custom header. - if len(c.header) > 0 { - for k, v := range c.header { - req.Header.Set(k, v) - } - } - // Custom Cookie. - if len(c.cookies) > 0 { - headerCookie := "" - for k, v := range c.cookies { - if len(headerCookie) > 0 { - headerCookie += ";" - } - headerCookie += k + "=" + v - } - if len(headerCookie) > 0 { - req.Header.Set("Cookie", headerCookie) - } - } - // HTTP basic authentication. - if len(c.authUser) > 0 { - req.SetBasicAuth(c.authUser, c.authPass) - } - // Sending request. - r := (*http.Response)(nil) - for { - if r, err = c.Do(req); err != nil { - if c.retryCount > 0 { - c.retryCount-- - } else { - return nil, err - } - } else { - break - } - } - resp = &ClientResponse{ - cookies: make(map[string]string), - } - resp.Response = r - // Auto saving cookie content. - if c.browserMode { - now := time.Now() - for _, v := range r.Cookies() { - if v.Expires.UnixNano() < now.UnixNano() { - delete(c.cookies, v.Name) - } else { - c.cookies[v.Name] = v.Value - } - } - } - return resp, nil +func (c *Client) Post(url string, data ...interface{}) (*ClientResponse, error) { + return c.DoRequest("POST", url, data...) } // Delete send DELETE request and returns the response object. @@ -194,10 +78,13 @@ func (c *Client) Trace(url string, data ...interface{}) (*ClientResponse, error) // DoRequest sends request with given HTTP method and data and returns the response object. // Note that the response object MUST be closed if it'll be never used. -func (c *Client) DoRequest(method, url string, data ...interface{}) (*ClientResponse, error) { - if strings.EqualFold("POST", method) { - return c.Post(url, data...) - } +// +// Note that it uses "multipart/form-data" as its Content-Type if it contains file uploading, +// else it uses "application/x-www-form-urlencoded". It also automatically detects the post +// content for JSON format, and for that it automatically sets the Content-Type as +// "application/json". +func (c *Client) DoRequest(method, url string, data ...interface{}) (resp *ClientResponse, err error) { + method = strings.ToUpper(method) if len(c.prefix) > 0 { url = c.prefix + url } @@ -205,22 +92,69 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (*ClientResp if len(data) > 0 { param = BuildParams(data[0]) } - req, err := http.NewRequest(strings.ToUpper(method), url, bytes.NewReader([]byte(param))) - if err != nil { - return nil, err + req := (*http.Request)(nil) + if strings.Contains(param, "@file:") { + // File uploading request. + buffer := new(bytes.Buffer) + writer := multipart.NewWriter(buffer) + defer writer.Close() + for _, item := range strings.Split(param, "&") { + array := strings.Split(item, "=") + if len(array[1]) > 6 && strings.Compare(array[1][0:6], "@file:") == 0 { + path := array[1][6:] + if !gfile.Exists(path) { + return nil, errors.New(fmt.Sprintf(`"%s" does not exist`, path)) + } + if file, err := writer.CreateFormFile(array[0], path); err == nil { + if f, err := os.Open(path); err == nil { + defer f.Close() + if _, err = io.Copy(file, f); err != nil { + return nil, err + } + } else { + return nil, err + } + } else { + return nil, err + } + } else { + if err := writer.WriteField(array[0], array[1]); err != nil { + return nil, err + } + } + } + if req, err = http.NewRequest(method, url, buffer); err != nil { + return nil, err + } else { + req.Header.Set("Content-Type", writer.FormDataContentType()) + } + } else { + // Normal request. + paramBytes := []byte(param) + if req, err = http.NewRequest(method, url, bytes.NewReader(paramBytes)); err != nil { + return nil, err + } else { + if v, ok := c.header["Content-Type"]; ok { + // Custom Content-Type. + req.Header.Set("Content-Type", v) + } else { + if json.Valid(paramBytes) { + // Auto detecting and setting the post content format: JSON. + req.Header.Set("Content-Type", "application/json") + } else if gregex.IsMatchString(`^[\w\[\]]+=.+`, param) { + // If the parameters passed like "name=value", it then uses form type. + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } + } + } } - // custom header. + // Custom header. if len(c.header) > 0 { for k, v := range c.header { req.Header.Set(k, v) } } - // Automatically set default content type to "application/x-www-form-urlencoded" - // if there' no content type set. - if _, ok := c.header["Content-Type"]; !ok { - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - } - // Custom cookie. + // Custom Cookie. if len(c.cookies) > 0 { headerCookie := "" for k, v := range c.cookies { @@ -233,27 +167,29 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (*ClientResp req.Header.Set("Cookie", headerCookie) } } + // HTTP basic authentication. + if len(c.authUser) > 0 { + req.SetBasicAuth(c.authUser, c.authPass) + } // Sending request. - resp := (*http.Response)(nil) + var r *http.Response for { - if r, err := c.Do(req); err != nil { + if r, err = c.Do(req); err != nil { if c.retryCount > 0 { c.retryCount-- } else { return nil, err } } else { - resp = r break } } - r := &ClientResponse{ - Response: resp, + resp = &ClientResponse{ + Response: r, } - // Auto sending cookie content. + // Auto saving cookie content. if c.browserMode { now := time.Now() - r.cookies = make(map[string]string) for _, v := range r.Cookies() { if v.Expires.UnixNano() < now.UnixNano() { delete(c.cookies, v.Name) @@ -262,5 +198,5 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (*ClientResp } } } - return r, nil + return resp, nil } diff --git a/net/ghttp/ghttp_server.go b/net/ghttp/ghttp_server.go index a9e219b09..deb6a8d19 100644 --- a/net/ghttp/ghttp_server.go +++ b/net/ghttp/ghttp_server.go @@ -234,7 +234,7 @@ func GetServer(name ...interface{}) *Server { if s := serverMapping.Get(serverName); s != nil { return s.(*Server) } - c := defaultServerConfig + c := Config() s := &Server{ name: serverName, plugins: make([]Plugin, 0), diff --git a/net/ghttp/ghttp_server_config.go b/net/ghttp/ghttp_server_config.go index 074c57240..26e4660fc 100644 --- a/net/ghttp/ghttp_server_config.go +++ b/net/ghttp/ghttp_server_config.go @@ -79,49 +79,48 @@ type ServerConfig struct { Graceful bool // Other: Enable graceful reload feature for all servers of the process. } -// defaultServerConfig is the default configuration object for server. -var defaultServerConfig = ServerConfig{ - Address: "", - HTTPSAddr: "", - Handler: nil, - ReadTimeout: 60 * time.Second, - WriteTimeout: 60 * time.Second, - IdleTimeout: 60 * time.Second, - MaxHeaderBytes: 1024, - KeepAlive: true, - IndexFiles: []string{"index.html", "index.htm"}, - IndexFolder: false, - ServerAgent: "GF HTTP Server", - ServerRoot: "", - StaticPaths: make([]staticPathItem, 0), - FileServerEnabled: false, - CookieMaxAge: time.Hour * 24 * 365, - CookiePath: "/", - CookieDomain: "", - SessionMaxAge: time.Hour * 24, - SessionIdName: "gfsessionid", - SessionPath: gsession.DefaultStorageFilePath, - Logger: glog.New(), - LogStdout: true, - ErrorStack: true, - ErrorLogEnabled: true, - ErrorLogPattern: "error-{Ymd}.log", - AccessLogEnabled: false, - AccessLogPattern: "access-{Ymd}.log", - DumpRouterMap: true, - FormParsingMemory: 100 * 1024 * 1024, // 100MB - Rewrites: make(map[string]string), - Graceful: true, -} - // Config returns the default ServerConfig object. +// Note that, do not define this default configuration to local variable, +// as there're some pointer attributes that may be shared in different servers. func Config() ServerConfig { - return defaultServerConfig + return ServerConfig{ + Address: "", + HTTPSAddr: "", + Handler: nil, + ReadTimeout: 60 * time.Second, + WriteTimeout: 60 * time.Second, + IdleTimeout: 60 * time.Second, + MaxHeaderBytes: 1024, + KeepAlive: true, + IndexFiles: []string{"index.html", "index.htm"}, + IndexFolder: false, + ServerAgent: "GF HTTP Server", + ServerRoot: "", + StaticPaths: make([]staticPathItem, 0), + FileServerEnabled: false, + CookieMaxAge: time.Hour * 24 * 365, + CookiePath: "/", + CookieDomain: "", + SessionMaxAge: time.Hour * 24, + SessionIdName: "gfsessionid", + SessionPath: gsession.DefaultStorageFilePath, + Logger: glog.New(), + LogStdout: true, + ErrorStack: true, + ErrorLogEnabled: true, + ErrorLogPattern: "error-{Ymd}.log", + AccessLogEnabled: false, + AccessLogPattern: "access-{Ymd}.log", + DumpRouterMap: true, + FormParsingMemory: 100 * 1024 * 1024, // 100MB + Rewrites: make(map[string]string), + Graceful: true, + } } // ConfigFromMap creates and returns a ServerConfig object with given map. func ConfigFromMap(m map[string]interface{}) (ServerConfig, error) { - config := defaultServerConfig + config := Config() if err := gconv.Struct(m, &config); err != nil { return config, err } diff --git a/net/ghttp/ghttp_server_config_logging.go b/net/ghttp/ghttp_server_config_logging.go index 3197db4ac..110ba758c 100644 --- a/net/ghttp/ghttp_server_config_logging.go +++ b/net/ghttp/ghttp_server_config_logging.go @@ -6,11 +6,14 @@ package ghttp +import "github.com/gogf/gf/internal/intlog" + // 设置日志目录,只有在设置了日志目录的情况下才会输出日志到日志文件中。 func (s *Server) SetLogPath(path string) { if len(path) == 0 { return } + intlog.Print("SetLogPath:", path) s.config.LogPath = path s.config.ErrorLogEnabled = true s.config.AccessLogEnabled = true