improve configuration feature for ghttp.Server

This commit is contained in:
John
2019-11-07 16:40:34 +08:00
parent 05120b585d
commit ad7375b44b
10 changed files with 99 additions and 60 deletions

View File

@ -1,11 +1,12 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
func main() {
s := ghttp.GetServer()
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.Writeln("来自于HTTPS的哈喽世界")
})

View File

@ -1,11 +1,12 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
func main() {
s := ghttp.GetServer()
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.Writeln("您可以同时通过HTTP和HTTPS方式看到该内容")
})

View File

@ -0,0 +1,7 @@
[server]
LogPath = "/tmp/gflog/server"
LogStdout = true
ErrorLogEnabled = true
ErrorLogPattern = "error.log"
AccessLogEnabled = true
AccessLogPattern = "access.log"

View File

@ -1,26 +1,21 @@
package main
import (
"net/http"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"net/http"
)
func main() {
s := ghttp.GetServer()
s.BindHandler("/log/handler", func(r *ghttp.Request) {
r.Response.WriteStatus(http.StatusNotFound, "文件找不到了")
s := g.Server()
s.Group("/", func(g *ghttp.RouterGroup) {
g.ALL("/", func(r *ghttp.Request) {
r.Response.Write("halo world!")
})
g.ALL("/log/handler", func(r *ghttp.Request) {
r.Response.WriteStatus(http.StatusNotFound, "File Not Found!")
})
})
s.SetAccessLogEnabled(true)
s.SetErrorLogEnabled(true)
//s.SetLogHandler(func(r *ghttp.Request, error ...interface{}) {
// if len(error) > 0 {
// // 如果是错误日志
// fmt.Println("错误产生了:", error[0])
// }
// // 这里是请求日志
// fmt.Println("请求处理完成,请求地址:", r.URL.String(), "请求结果:", r.Response.Status)
//})
s.SetPort(8199)
s.Run()
}

View File

@ -6,7 +6,7 @@ import (
func main() {
s := ghttp.GetServer()
s.EnablePprof()
s.EnablePProf()
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.Writeln("哈喽世界!")
})

View File

@ -176,10 +176,9 @@ func SetGraceful(enabled bool) {
// Web Server进程初始化.
// 注意该方法不能放置于包初始化方法init中不使用ghttp.Server的功能便不能初始化对应的协程goroutine逻辑.
func serverProcessInit() {
if serverProcessInited.Val() {
if !serverProcessInited.Cas(false, true) {
return
}
serverProcessInited.Set(true)
// 如果是完整重启,那么需要等待主进程销毁后,才开始执行监听,防止端口冲突
if genv.Get(gADMIN_ACTION_RESTART_ENVKEY) != "" {
if p, e := os.FindProcess(gproc.PPid()); e == nil {
@ -251,7 +250,7 @@ func (s *Server) Start() error {
// 没有注册任何路由,且没有开启文件服务,那么提示错误
if len(s.routesMap) == 0 && !s.config.FileServerEnabled {
glog.Fatal("[ghttp] no router set or static feature enabled, did you forget import the router?")
glog.Fatal("[ghttp] There's no route set or static feature enabled, did you forget import the router?")
}
// Default session storage.
@ -261,12 +260,17 @@ func (s *Server) Start() error {
// Initialize session manager when start running.
s.sessionManager = gsession.New(s.config.SessionMaxAge, s.config.SessionStorage)
// 底层http server配置
// PProf feature.
if s.config.PProfEnabled {
s.EnablePProf(s.config.PProfPattern)
}
// Default HTTP handler.
if s.config.Handler == nil {
s.config.Handler = http.HandlerFunc(s.defaultHttpHandle)
}
// 启动http server
// Start the HTTP server.
reloaded := false
fdMapStr := genv.Get(gADMIN_ACTION_RELOAD_ENVKEY)
if len(fdMapStr) > 0 {
@ -421,7 +425,7 @@ func Wait() {
func (s *Server) startServer(fdMap listenerFdMap) {
var httpsEnabled bool
// 判断是否启用HTTPS
if len(s.config.TLSConfig.Certificates) > 0 || (len(s.config.HTTPSCertPath) > 0 && len(s.config.HTTPSKeyPath) > 0) {
if s.config.TLSConfig != nil || (s.config.HTTPSCertPath != "" && s.config.HTTPSKeyPath != "") {
// ================
// HTTPS
// ================
@ -502,7 +506,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, &s.config.TLSConfig)
err = server.ListenAndServeTLS(s.config.HTTPSCertPath, s.config.HTTPSKeyPath, s.config.TLSConfig)
} else {
err = server.ListenAndServe()
}

View File

@ -32,10 +32,10 @@ const (
URI_TYPE_CAMEL = 3 // 采用驼峰命名方式
)
// 自定义日志处理方法类型
// LogHandler is the log handler function type.
type LogHandler func(r *Request, err ...error)
// HTTP Server 设置结构体,静态配置
// HTTP Server configuration.
type ServerConfig struct {
Address string // Server listening address like ":port", multiple addresses separated using ','
HTTPSAddr string // HTTPS服务监听地址(支持多个地址,使用","号分隔)
@ -46,7 +46,7 @@ type ServerConfig struct {
WriteTimeout time.Duration // 写入超时
IdleTimeout time.Duration // 等待超时
MaxHeaderBytes int // 最大的header长度
TLSConfig tls.Config // HTTPS证书配置
TLSConfig *tls.Config // HTTPS证书配置
KeepAlive bool // 是否开启长连接
ServerAgent string // Server Agent
View *gview.View // 模板引擎对象
@ -71,7 +71,11 @@ type ServerConfig struct {
LogStdout bool // Logging: 是否打印日志到终端(默认开启)
ErrorStack bool // Logging: 当产生错误时打印调用链详细堆栈
ErrorLogEnabled bool // Logging: 是否开启error log(默认开启)
ErrorLogPattern string // Logging: Error log file pattern like: error-{Ymd}.log
AccessLogEnabled bool // Logging: 是否开启access log(默认关闭)
AccessLogPattern string // Logging: Error log file pattern like: access-{Ymd}.log
PProfEnabled bool // PProf: Enable PProf feature or not.
PProfPattern string // PProf: PProf pattern for router, it enables PProf feature if it's not empty.
FormParsingMemory int64 // Mess: 表单解析内存限制(byte)
NameToUriType int // Mess: 服务注册时对象和方法名称转换为URI时的规则
GzipContentTypes []string // Mess: 允许进行gzip压缩的文件类型
@ -91,7 +95,7 @@ var defaultServerConfig = ServerConfig{
KeepAlive: true,
IndexFiles: []string{"index.html", "index.htm"},
IndexFolder: false,
ServerAgent: "gf http server",
ServerAgent: "GF HTTP Server",
ServerRoot: "",
StaticPaths: make([]staticPathItem, 0),
FileServerEnabled: false,
@ -103,7 +107,9 @@ var defaultServerConfig = ServerConfig{
LogStdout: true,
ErrorStack: true,
ErrorLogEnabled: true,
ErrorLogPattern: "error-{Ymd}.log",
AccessLogEnabled: false,
AccessLogPattern: "access-{Ymd}.log",
DumpRouteMap: true,
FormParsingMemory: 1024 * 1024 * 1024,
RouterCacheExpire: 60,
@ -131,10 +137,14 @@ func (s *Server) SetConfig(c ServerConfig) error {
c.Handler = http.HandlerFunc(s.defaultHttpHandle)
}
s.config = c
// Logging.
if c.LogPath != "" {
return s.logger.SetPath(c.LogPath)
}
// HTTPS.
if c.TLSConfig == nil && c.HTTPSCertPath != "" {
s.EnableHTTPS(c.HTTPSCertPath, c.HTTPSKeyPath)
}
return nil
}
@ -185,7 +195,7 @@ func (s *Server) SetHTTPSPort(port ...int) {
}
// 开启HTTPS支持但是必须提供Cert和Key文件tlsConfig为可选项
func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...tls.Config) {
func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...*tls.Config) {
certFileRealPath := gfile.RealPath(certFile)
if certFileRealPath == "" {
certFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + certFile)
@ -214,7 +224,7 @@ func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...tls.Config)
}
// 设置TLS配置对象
func (s *Server) SetTLSConfig(tlsConfig tls.Config) {
func (s *Server) SetTLSConfig(tlsConfig *tls.Config) {
s.config.TLSConfig = tlsConfig
}

View File

@ -91,11 +91,13 @@ func (s *gracefulServer) setFd(fd int) {
// 执行HTTPS监听
func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string, tlsConfig ...*tls.Config) error {
itemFunc := s.httpServer.Addr
config := (*tls.Config)(nil)
if len(tlsConfig) > 0 {
var config *tls.Config
if len(tlsConfig) > 0 && tlsConfig[0] != nil {
config = tlsConfig[0]
} else if s.httpServer.TLSConfig != nil {
*config = *s.httpServer.TLSConfig
config = s.httpServer.TLSConfig
} else {
config = &tls.Config{}
}
if config.NextProtos == nil {
config.NextProtos = []string{"http/1.1"}

View File

@ -38,7 +38,7 @@ func (s *Server) handleAccessLog(r *Request) {
)
content += fmt.Sprintf(` %.3f`, float64(r.LeaveTime-r.EnterTime)/1000)
content += fmt.Sprintf(`, %s, "%s", "%s"`, r.GetClientIp(), r.Referer(), r.UserAgent())
s.logger.Cat("access").StackWithFilter(gPATH_FILTER_KEY).Stdout(s.config.LogStdout).Println(content)
s.logger.File(s.config.AccessLogPattern).StackWithFilter(gPATH_FILTER_KEY).Stdout(s.config.LogStdout).Println(content)
}
// 处理服务错误信息主要是panichttp请求的status由access log进行管理
@ -71,5 +71,5 @@ func (s *Server) handleErrorLog(err error, r *Request) {
content += "\n" + stack
}
}
s.logger.Cat("error").Stack(false).Stdout(s.config.LogStdout).Error(content)
s.logger.File(s.config.AccessLogPattern).Stack(false).Stdout(s.config.LogStdout).Error(content)
}

View File

@ -15,10 +15,33 @@ import (
"github.com/gogf/gf/os/gview"
)
// 用于pprof的对象
type utilPprof struct{}
// utilPProf is the PProf interface implementer.
type utilPProf struct{}
func (p *utilPprof) Index(r *Request) {
const (
gDEFAULT_PPROF_PATTERN = "/debug/pprof"
)
// EnablePProf enables PProf feature for server.
func (s *Server) EnablePProf(pattern ...string) {
p := gDEFAULT_PPROF_PATTERN
if len(pattern) > 0 && pattern[0] != "" {
p = pattern[0]
}
up := &utilPProf{}
_, _, uri, _ := s.parsePattern(p)
uri = strings.TrimRight(uri, "/")
s.Group(uri, func(g *RouterGroup) {
g.ALL("/*action", up.Index)
g.ALL("/cmdline", up.Cmdline)
g.ALL("/profile", up.Profile)
g.ALL("/symbol", up.Symbol)
g.ALL("/trace", up.Trace)
})
}
// Index shows the PProf index page.
func (p *utilPProf) Index(r *Request) {
profiles := runpprof.Profiles()
action := r.GetString("action")
data := map[string]interface{}{
@ -52,34 +75,30 @@ func (p *utilPprof) Index(r *Request) {
}
}
func (p *utilPprof) Cmdline(r *Request) {
// Cmdline responds with the running program's
// command line, with arguments separated by NUL bytes.
// The package initialization registers it as /debug/pprof/cmdline.
func (p *utilPProf) Cmdline(r *Request) {
netpprof.Cmdline(r.Response.Writer, r.Request)
}
func (p *utilPprof) Profile(r *Request) {
// Profile responds with the pprof-formatted cpu profile.
// Profiling lasts for duration specified in seconds GET parameter, or for 30 seconds if not specified.
// The package initialization registers it as /debug/pprof/profile.
func (p *utilPProf) Profile(r *Request) {
netpprof.Profile(r.Response.Writer, r.Request)
}
func (p *utilPprof) Symbol(r *Request) {
// Symbol looks up the program counters listed in the request,
// responding with a table mapping program counters to function names.
// The package initialization registers it as /debug/pprof/symbol.
func (p *utilPProf) Symbol(r *Request) {
netpprof.Symbol(r.Response.Writer, r.Request)
}
func (p *utilPprof) Trace(r *Request) {
// Trace responds with the execution trace in binary form.
// Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified.
// The package initialization registers it as /debug/pprof/trace.
func (p *utilPProf) Trace(r *Request) {
netpprof.Trace(r.Response.Writer, r.Request)
}
// 开启pprof支持
func (s *Server) EnablePprof(pattern ...string) {
p := "/debug/pprof"
if len(pattern) > 0 {
p = pattern[0]
}
up := &utilPprof{}
_, _, uri, _ := s.parsePattern(p)
uri = strings.TrimRight(uri, "/")
s.BindHandler(uri+"/*action", up.Index)
s.BindHandler(uri+"/cmdline", up.Cmdline)
s.BindHandler(uri+"/profile", up.Profile)
s.BindHandler(uri+"/symbol", up.Symbol)
s.BindHandler(uri+"/trace", up.Trace)
}