mirror of
https://gitee.com/johng/gf
synced 2026-07-06 13:42:46 +08:00
improve configuration feature for ghttp.Server
This commit is contained in:
@ -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的:哈喽世界!")
|
||||
})
|
||||
|
||||
@ -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方式看到该内容!")
|
||||
})
|
||||
|
||||
7
.example/net/ghttp/server/log/config.toml
Normal file
7
.example/net/ghttp/server/log/config.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[server]
|
||||
LogPath = "/tmp/gflog/server"
|
||||
LogStdout = true
|
||||
ErrorLogEnabled = true
|
||||
ErrorLogPattern = "error.log"
|
||||
AccessLogEnabled = true
|
||||
AccessLogPattern = "access.log"
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import (
|
||||
|
||||
func main() {
|
||||
s := ghttp.GetServer()
|
||||
s.EnablePprof()
|
||||
s.EnablePProf()
|
||||
s.BindHandler("/", func(r *ghttp.Request) {
|
||||
r.Response.Writeln("哈喽世界!")
|
||||
})
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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"}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
// 处理服务错误信息,主要是panic,http请求的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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user