diff --git a/config/configs.go b/config/configs.go index be9c389..857dee8 100644 --- a/config/configs.go +++ b/config/configs.go @@ -41,16 +41,17 @@ type ( } ServerNode struct { - EnabledListDir bool `xml:"enabledlistdir,attr"` //设置是否启用目录浏览,仅对Router.ServerFile有效,若设置该项,则可以浏览目录文件,默认不开启 - EnabledGzip bool `xml:"enabledgzip,attr"` //是否启用gzip - EnabledAutoHEAD bool `xml:"enabledautohead,attr"` //设置是否自动启用Head路由,若设置该项,则会为除Websocket\HEAD外所有路由方式默认添加HEAD路由,默认不开启 - EnabledAutoCORS bool `xml:"enabledautocors,attr"` //设置是否自动跨域支持,若设置,默认“GET, POST, PUT, DELETE, OPTIONS”全部请求均支持跨域 - EnabledIgnoreFavicon bool `xml:"enabledignorefavicon,attr"` //设置是否忽略favicon.ico请求,若设置,网站将把所有favicon.ico请求直接空返回 - Port int `xml:"port,attr"` //端口 - EnabledTLS bool `xml:"enabledtls,attr"` //是否启用TLS模式 - TLSCertFile string `xml:"tlscertfile,attr"` //TLS模式下Certificate证书文件地址 - TLSKeyFile string `xml:"tlskeyfile,attr"` //TLS模式下秘钥文件地址 - IndexPage string `xml:"indexpage,attr"` //默认index页面 + EnabledListDir bool `xml:"enabledlistdir,attr"` //设置是否启用目录浏览,仅对Router.ServerFile有效,若设置该项,则可以浏览目录文件,默认不开启 + EnabledGzip bool `xml:"enabledgzip,attr"` //是否启用gzip + EnabledAutoHEAD bool `xml:"enabledautohead,attr"` //设置是否自动启用Head路由,若设置该项,则会为除Websocket\HEAD外所有路由方式默认添加HEAD路由,默认不开启 + EnabledAutoCORS bool `xml:"enabledautocors,attr"` //设置是否自动跨域支持,若设置,默认“GET, POST, PUT, DELETE, OPTIONS”全部请求均支持跨域 + EnabledIgnoreFavicon bool `xml:"enabledignorefavicon,attr"` //设置是否忽略favicon.ico请求,若设置,网站将把所有favicon.ico请求直接空返回 + Port int `xml:"port,attr"` //端口 + EnabledTLS bool `xml:"enabledtls,attr"` //是否启用TLS模式 + TLSCertFile string `xml:"tlscertfile,attr"` //TLS模式下Certificate证书文件地址 + TLSKeyFile string `xml:"tlskeyfile,attr"` //TLS模式下秘钥文件地址 + IndexPage string `xml:"indexpage,attr"` //默认index页面 + EnabledDetailRequestData bool `xml:"enableddetailrequestdata,attr"` //设置状态数据是否启用详细页面统计,默认不启用,请特别对待,如果站点url过多,会导致数据量过大 } SessionNode struct { diff --git a/context.go b/context.go index f673ad3..622e46a 100644 --- a/context.go +++ b/context.go @@ -254,7 +254,7 @@ func (ctx *HttpContext) Session() (state *session.SessionState) { //return nil, errors.New("no effective http-server") panic("no effective http-server") } - if !ctx.httpServer.SessionConfig.EnabledSession { + if !ctx.httpServer.SessionConfig().EnabledSession { //return nil, errors.New("http-server not enabled session") panic("http-server not enabled session") } diff --git a/core/state.go b/core/state.go index 8958dd6..f0af9cc 100644 --- a/core/state.go +++ b/core/state.go @@ -2,6 +2,7 @@ package core import ( "github.com/devfeel/dotweb/framework/json" + "net/http" "strconv" "strings" "sync" @@ -20,18 +21,18 @@ const ( func init() { GlobalState = &ServerStateInfo{ - ServerStartTime: time.Now(), - TotalRequestCount: 0, - TotalErrorCount: 0, - IntervalRequestData: NewItemContext(), - DetailRequestPageData: NewItemContext(), - IntervalErrorData: NewItemContext(), - DetailErrorPageData: NewItemContext(), - DetailErrorData: NewItemContext(), - DetailHTTPCodeData: NewItemContext(), - dataChan_Request: make(chan *RequestInfo, 1000), - dataChan_Error: make(chan *ErrorInfo, 1000), - dataChan_HttpCode: make(chan *HttpCodeInfo, 1000), + ServerStartTime: time.Now(), + TotalRequestCount: 0, + TotalErrorCount: 0, + IntervalRequestData: NewItemContext(), + DetailRequestUrlData: NewItemContext(), + IntervalErrorData: NewItemContext(), + DetailErrorPageData: NewItemContext(), + DetailErrorData: NewItemContext(), + DetailHTTPCodeData: NewItemContext(), + dataChan_Request: make(chan *RequestInfo, 1000), + dataChan_Error: make(chan *ErrorInfo, 1000), + dataChan_HttpCode: make(chan *HttpCodeInfo, 1000), infoPool: &pool{ requestInfo: sync.Pool{ New: func() interface{} { @@ -63,8 +64,9 @@ type pool struct { //http request count info type RequestInfo struct { - Url string - Num uint64 + Url string + Code int + Num uint64 } //error count info @@ -85,12 +87,14 @@ type HttpCodeInfo struct { type ServerStateInfo struct { //服务启动时间 ServerStartTime time.Time + //是否启用详细请求数据统计 fixed #63 状态数据,当url较多时,导致内存占用过大 + EnabledDetailRequestData bool //该运行期间总访问次数 TotalRequestCount uint64 //单位时间内请求数据 - 按分钟为单位 IntervalRequestData *ItemContext //明细请求页面数据 - 以不带参数的访问url为key - DetailRequestPageData *ItemContext + DetailRequestUrlData *ItemContext //该运行期间异常次数 TotalErrorCount uint64 //单位时间内异常次数 - 按分钟为单位 @@ -122,9 +126,9 @@ func (state *ServerStateInfo) ShowHtmlData() string { data += "IntervalRequestData : " + jsonutil.GetJsonString(state.IntervalRequestData.GetCurrentMap()) state.IntervalRequestData.RUnlock() data += "
" - state.DetailRequestPageData.RLock() - data += "DetailRequestPageData : " + jsonutil.GetJsonString(state.DetailRequestPageData.GetCurrentMap()) - state.DetailRequestPageData.RUnlock() + state.DetailRequestUrlData.RLock() + data += "DetailRequestUrlData : " + jsonutil.GetJsonString(state.DetailRequestUrlData.GetCurrentMap()) + state.DetailRequestUrlData.RUnlock() data += "
" state.IntervalErrorData.RLock() data += "IntervalErrorData : " + jsonutil.GetJsonString(state.IntervalErrorData.GetCurrentMap()) @@ -156,20 +160,13 @@ func (state *ServerStateInfo) QueryIntervalErrorData(queryKey string) uint64 { } //AddRequestCount 增加请求数 -func (state *ServerStateInfo) AddRequestCount(page string, num uint64) uint64 { +func (state *ServerStateInfo) AddRequestCount(page string, code int, num uint64) uint64 { if strings.Index(page, "/dotweb/") != 0 { atomic.AddUint64(&state.TotalRequestCount, num) - state.addRequestData(page, num) - } - return state.TotalRequestCount -} - -//AddHttpCodeCount 增加Http状态码数据 -func (state *ServerStateInfo) AddTTPCodeCount(page string, code int, num uint64) uint64 { - if strings.Index(page, "/dotweb/") != 0 { + state.addRequestData(page, code, num) state.addHTTPCodeData(page, code, num) } - return state.TotalErrorCount + return state.TotalRequestCount } //AddErrorCount 增加错误数 @@ -179,10 +176,11 @@ func (state *ServerStateInfo) AddErrorCount(page string, err error, num uint64) return state.TotalErrorCount } -func (state *ServerStateInfo) addRequestData(page string, num uint64) { +func (state *ServerStateInfo) addRequestData(page string, code int, num uint64) { //get from pool info := state.infoPool.requestInfo.Get().(*RequestInfo) info.Url = page + info.Code = code info.Num = num state.dataChan_Request <- info } @@ -211,14 +209,19 @@ func (state *ServerStateInfo) handleInfo() { select { case info := <-state.dataChan_Request: { - //set detail page data - key := strings.ToLower(info.Url) - val := state.DetailRequestPageData.GetUInt64(key) - state.DetailRequestPageData.Set(key, val+info.Num) - + //fixed #63 状态数据,当url较多时,导致内存占用过大 + if state.EnabledDetailRequestData { + //ignore 404 request + if info.Code != http.StatusNotFound { + //set detail url data + key := strings.ToLower(info.Url) + val := state.DetailRequestUrlData.GetUInt64(key) + state.DetailRequestUrlData.Set(key, val+info.Num) + } + } //set interval data - key = time.Now().Format(minuteTimeLayout) - val = state.IntervalRequestData.GetUInt64(key) + key := time.Now().Format(minuteTimeLayout) + val := state.IntervalRequestData.GetUInt64(key) state.IntervalRequestData.Set(key, val+info.Num) //put info obj diff --git a/dotweb.go b/dotweb.go index bdd12d0..21e5d56 100644 --- a/dotweb.go +++ b/dotweb.go @@ -24,20 +24,23 @@ import ( type ( DotWeb struct { - HttpServer *HttpServer - cache cache.Cache - OfflineServer servers.Server - Config *config.Config - Middlewares []Middleware - ExceptionHandler ExceptionHandle - NotFoundHandler NotFoundHandle - AppContext *core.ItemContext - middlewareMap map[string]MiddlewareFunc - middlewareMutex *sync.RWMutex + HttpServer *HttpServer + cache cache.Cache + OfflineServer servers.Server + Config *config.Config + Middlewares []Middleware + ExceptionHandler ExceptionHandle + NotFoundHandler NotFoundHandle + MethodNotAllowedHandler MethodNotAllowedHandle + AppContext *core.ItemContext + middlewareMap map[string]MiddlewareFunc + middlewareMutex *sync.RWMutex } ExceptionHandle func(Context, error) - NotFoundHandle func(http.ResponseWriter, *http.Request) + //fixed for #64 增加MethodNotAllowed自定义处理 + MethodNotAllowedHandle func(Context) + NotFoundHandle func(Context) // Handle is a function that can be registered to a route to handle HTTP // requests. Like http.HandlerFunc, but has a special parameter Context contain all request and response data. @@ -153,6 +156,11 @@ func (app *DotWeb) SetNotFoundHandle(handler NotFoundHandle) { app.NotFoundHandler = handler } +// SetMethodNotAllowedHandle set custom 405 handler +func (app *DotWeb) SetMethodNotAllowedHandle(handler MethodNotAllowedHandle) { + app.MethodNotAllowedHandler = handler +} + // SetPProfConfig set pprofserver config, default is disable // and don't use same port with StartServer func (app *DotWeb) SetPProfConfig(enabledPProf bool, httpport int) { @@ -180,6 +188,59 @@ func (app *DotWeb) SetEnabledLog(enabledLog bool) { func (app *DotWeb) SetConfig(config *config.Config) error { app.Config = config + return nil +} + +// StartServer start server with http port +// if config the pprof, will be start pprof server +func (app *DotWeb) StartServer(httpport int) error { + addr := ":" + strconv.Itoa(httpport) + return app.ListenAndServe(addr) +} + +// Start start app server with set config +// If an exception occurs, will be return it +// if no set Server.Port, will be use DefaultHttpPort +func (app *DotWeb) Start() error { + if app.Config == nil { + return errors.New("no config set!") + } + //start server + port := app.Config.Server.Port + if port <= 0 { + port = DefaultHttpPort + } + return app.StartServer(port) +} + +// MustStart start app server with set config +// If an exception occurs, will be panic it +// if no set Server.Port, will be use DefaultHttpPort +func (app *DotWeb) MustStart() { + err := app.Start() + if err != nil { + panic(err) + } +} + +// ListenAndServe start server with addr +// not support pprof server auto start +func (app *DotWeb) ListenAndServe(addr string) error { + app.initAppConfig() + app.initServerEnvironment() + app.initInnerRouter() + if app.HttpServer.ServerConfig().EnabledTLS { + err := app.HttpServer.ListenAndServeTLS(addr, app.HttpServer.ServerConfig().TLSCertFile, app.HttpServer.ServerConfig().TLSKeyFile) + return err + } + err := app.HttpServer.ListenAndServe(addr) + return err + +} + +// init App Config +func (app *DotWeb) initAppConfig() { + config := app.Config //log config if config.App.LogPath != "" { logger.SetLogPath(config.App.LogPath) @@ -212,6 +273,11 @@ func (app *DotWeb) SetConfig(config *config.Config) error { app.HttpServer.SetSessionConfig(session.NewStoreConfig(config.Session.SessionMode, config.Session.Timeout, config.Session.ServerIP)) } + //设置启用详细请求数据统计 + if config.Server.EnabledDetailRequestData { + core.GlobalState.EnabledDetailRequestData = config.Server.EnabledDetailRequestData + } + //register app's middleware for _, m := range config.Middlewares { if m.IsUse { @@ -265,53 +331,6 @@ func (app *DotWeb) SetConfig(config *config.Config) error { } } } - return nil -} - -// StartServer start server with http port -// if config the pprof, will be start pprof server -func (app *DotWeb) StartServer(httpport int) error { - addr := ":" + strconv.Itoa(httpport) - return app.ListenAndServe(addr) -} - -// Start start app server with set config -// If an exception occurs, will be return it -// if no set Server.Port, will be use DefaultHttpPort -func (app *DotWeb) Start() error { - if app.Config == nil { - return errors.New("no config set!") - } - //start server - port := app.Config.Server.Port - if port <= 0 { - port = DefaultHttpPort - } - return app.StartServer(port) -} - -// MustStart start app server with set config -// If an exception occurs, will be panic it -// if no set Server.Port, will be use DefaultHttpPort -func (app *DotWeb) MustStart() { - err := app.Start() - if err != nil { - panic(err) - } -} - -// ListenAndServe start server with addr -// not support pprof server auto start -func (app *DotWeb) ListenAndServe(addr string) error { - app.initServerEnvironment() - app.initInnerRouter() - if app.HttpServer.ServerConfig.EnabledTLS { - err := app.HttpServer.ListenAndServeTLS(addr, app.HttpServer.ServerConfig.TLSCertFile, app.HttpServer.ServerConfig.TLSKeyFile) - return err - } - err := app.HttpServer.ListenAndServe(addr) - return err - } // init inner routers @@ -325,14 +344,23 @@ func (app *DotWeb) initInnerRouter() { gInner.GET("/query/:key", showQuery) } +// init Server Environment func (app *DotWeb) initServerEnvironment() { if app.ExceptionHandler == nil { app.SetExceptionHandle(app.DefaultHTTPErrorHandler) } + if app.NotFoundHandler == nil { + app.SetNotFoundHandle(app.DefaultNotFoundHandler) + } + + if app.MethodNotAllowedHandler == nil { + app.SetMethodNotAllowedHandle(app.DefaultMethodNotAllowedHandler) + } + //init session manager - if app.HttpServer.SessionConfig.EnabledSession { - if app.HttpServer.SessionConfig.SessionMode == "" { + if app.HttpServer.SessionConfig().EnabledSession { + if app.HttpServer.SessionConfig().SessionMode == "" { //panic("no set SessionConfig, but set enabledsession true") logger.Logger().Warn("not set SessionMode, but set enabledsession true, now will use default runtime session", LogTarget_HttpServer) app.HttpServer.SetSessionConfig(session.NewDefaultRuntimeConfig()) @@ -380,6 +408,18 @@ func (app *DotWeb) DefaultHTTPErrorHandler(ctx Context, err error) { } } +// DefaultNotFoundHandler default exception handler +func (app *DotWeb) DefaultNotFoundHandler(ctx Context) { + ctx.Response().Header().Set(HeaderContentType, CharsetUTF8) + ctx.WriteStringC(http.StatusNotFound, http.StatusText(http.StatusNotFound)) +} + +// DefaultNotFoundHandler default exception handler +func (app *DotWeb) DefaultMethodNotAllowedHandler(ctx Context) { + ctx.Response().Header().Set(HeaderContentType, CharsetUTF8) + ctx.WriteStringC(http.StatusMethodNotAllowed, http.StatusText(http.StatusMethodNotAllowed)) +} + // Close immediately stops the server. // It internally calls `http.Server#Close()`. func (app *DotWeb) Close() error { diff --git a/example/main.go b/example/main.go index 1c469a1..9ce5c0c 100644 --- a/example/main.go +++ b/example/main.go @@ -48,13 +48,14 @@ func main() { //redis mode //app.HttpServer.SetSessionConfig(session.NewDefaultRedisConfig("192.168.8.175:6379", "")) + app.HttpServer.SetEnabledDetailRequestData(true) + //设置路由 InitRoute(app.HttpServer) //自定义404输出 - app.SetNotFoundHandle(func(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("is't app's not found!")) + app.SetNotFoundHandle(func(ctx dotweb.Context) { + ctx.Response().Write(http.StatusNotFound, []byte("is't app's not found!")) }) //设置HttpModule diff --git a/feature.go b/feature.go index 15103cb..92cdb00 100644 --- a/feature.go +++ b/feature.go @@ -56,14 +56,14 @@ func (f *xFeatureTools) SetGzip(httpCtx *HttpContext) { func (f *xFeatureTools) InitFeatures(server *HttpServer, httpCtx *HttpContext) { //gzip - if server.ServerConfig.EnabledGzip { + if server.ServerConfig().EnabledGzip { FeatureTools.SetGzip(httpCtx) } //session //if exists client-sessionid, use it //if not exists client-sessionid, new one - if server.SessionConfig.EnabledSession { + if server.SessionConfig().EnabledSession { FeatureTools.SetSession(httpCtx) } @@ -78,7 +78,7 @@ func (f *xFeatureTools) InitFeatures(server *HttpServer, httpCtx *HttpContext) { } func (f *xFeatureTools) ReleaseFeatures(server *HttpServer, httpCtx *HttpContext) { - if server.ServerConfig.EnabledGzip { + if server.ServerConfig().EnabledGzip { var w io.Writer w = httpCtx.Response().Writer().(*gzipResponseWriter).Writer w.(*gzip.Writer).Close() diff --git a/router.go b/router.go index a766738..5a3be23 100644 --- a/router.go +++ b/router.go @@ -117,24 +117,9 @@ type ( // RedirectTrailingSlash is independent of this option. RedirectFixedPath bool - // If enabled, the router checks if another method is allowed for the - // current route, if the current request can not be routed. - // If this is the case, the request is answered with 'Method Not Allowed' - // and HTTP status code 405. - // If no other Method is allowed, the request is delegated to the NotFound - // handler. - HandleMethodNotAllowed bool - // If enabled, the router automatically replies to OPTIONS requests. // Custom OPTIONS handlers take priority over automatic replies. HandleOPTIONS bool - - // Configurable http.Handler which is called when a request - // cannot be routed and HandleMethodNotAllowed is true. - // If it is not set, http.Error with http.StatusMethodNotAllowed is used. - // The "Allow" header with allowed request methods is set before the handler - // is called. - MethodNotAllowed http.Handler } // Handle is a function that can be registered to a route to handle HTTP @@ -169,13 +154,12 @@ func (ps Params) ByName(name string) string { // Path auto-correction, including trailing slashes, is enabled by default. func NewRouter(server *HttpServer) *router { return &router{ - RedirectTrailingSlash: true, - RedirectFixedPath: true, - HandleMethodNotAllowed: true, - HandleOPTIONS: true, - server: server, - handlerMap: make(map[string]HttpHandle), - handlerMutex: new(sync.RWMutex), + RedirectTrailingSlash: true, + RedirectFixedPath: true, + HandleOPTIONS: true, + server: server, + handlerMap: make(map[string]HttpHandle), + handlerMutex: new(sync.RWMutex), } } @@ -202,9 +186,6 @@ func (r *router) MatchPath(ctx Context, routePath string) bool { // ServeHTTP makes the router implement the http.Handler interface. func (r *router) ServeHTTP(ctx *HttpContext) { - //增加状态计数 - core.GlobalState.AddRequestCount(ctx.Request().Path(), 1) - req := ctx.Request().Request w := ctx.Response().Writer() path := req.URL.Path @@ -258,28 +239,17 @@ func (r *router) ServeHTTP(ctx *HttpContext) { } } else { // Handle 405 - if r.HandleMethodNotAllowed { - if allow := r.allowed(path, req.Method); len(allow) > 0 { - w.Header().Set("Allow", allow) - if r.MethodNotAllowed != nil { - r.MethodNotAllowed.ServeHTTP(w, req) - } else { - http.Error(w, - http.StatusText(http.StatusMethodNotAllowed), - http.StatusMethodNotAllowed, - ) - } - return - } + if allow := r.allowed(path, req.Method); len(allow) > 0 { + w.Header().Set("Allow", allow) + ctx.Response().SetStatusCode(http.StatusMethodNotAllowed) + r.server.DotApp.MethodNotAllowedHandler(ctx) + return } } // Handle 404 - if r.server.DotApp.NotFoundHandler != nil { - r.server.DotApp.NotFoundHandler(w, req) - } else { - http.NotFound(w, req) - } + ctx.Response().SetStatusCode(http.StatusNotFound) + r.server.DotApp.NotFoundHandler(ctx) } //wrap HttpHandle to Handle @@ -359,8 +329,6 @@ func (r *router) wrapRouterHandle(handler HttpHandle, isHijack bool) RouterHandl //wrap fileHandler to httprouter.Handle func (r *router) wrapFileHandle(fileHandler http.Handler) RouterHandle { return func(httpCtx *HttpContext) { - //增加状态计数 - core.GlobalState.AddRequestCount(httpCtx.Request().Path(), 1) startTime := time.Now() httpCtx.Request().URL.Path = httpCtx.RouterParams().ByName("filepath") fileHandler.ServeHTTP(httpCtx.Response().Writer(), httpCtx.Request().Request) @@ -454,7 +422,7 @@ func (r *router) RegisterRoute(routeMethod string, path string, handle HttpHandl //if set auto-head, add head router //only enabled in hijack\GET\POST\DELETE\PUT\HEAD\PATCH\OPTIONS - if r.server.ServerConfig.EnabledAutoHEAD { + if r.server.ServerConfig().EnabledAutoHEAD { if routeMethod == RouteMethod_HiJack { r.add(RouteMethod_HEAD, path, r.wrapRouterHandle(handle, true)) } else if routeMethod != RouteMethod_Any { @@ -473,7 +441,7 @@ func (r *router) ServerFile(path string, fileroot string) RouterNode { } var root http.FileSystem root = http.Dir(fileroot) - if !r.server.ServerConfig.EnabledListDir { + if !r.server.ServerConfig().EnabledListDir { root = &core.HideReaddirFS{root} } fileServer := http.FileServer(root) @@ -599,9 +567,6 @@ func (r *router) wrapWebSocketHandle(handler HttpHandle) websocket.Handler { }() handler(httpCtx) - - //增加状态计数 - core.GlobalState.AddRequestCount(httpCtx.Request().Path(), 1) } } diff --git a/server.go b/server.go index f890ff6..658a0aa 100644 --- a/server.go +++ b/server.go @@ -31,8 +31,6 @@ type ( sessionManager *session.SessionManager lock_session *sync.RWMutex pool *pool - ServerConfig *config.ServerNode - SessionConfig *config.SessionNode binder Binder render Renderer offline bool @@ -66,12 +64,10 @@ func NewHttpServer() *HttpServer { }, }, }, - Modules: make([]*HttpModule, 0), - ServerConfig: config.NewServerNode(), - SessionConfig: config.NewSessionNode(), - lock_session: new(sync.RWMutex), - binder: newBinder(), - Features: &feature.Feature{}, + Modules: make([]*HttpModule, 0), + lock_session: new(sync.RWMutex), + binder: newBinder(), + Features: &feature.Feature{}, } //设置router server.router = NewRouter(server) @@ -79,6 +75,16 @@ func NewHttpServer() *HttpServer { return server } +// ServerConfig a shortcut for App.Config.ServerConfig +func (server *HttpServer) ServerConfig() *config.ServerNode { + return server.DotApp.Config.Server +} + +// SessionConfig a shortcut for App.Config.SessionConfig +func (server *HttpServer) SessionConfig() *config.SessionNode { + return server.DotApp.Config.Session +} + // ListenAndServe listens on the TCP network address srv.Addr and then // calls Serve to handle requests on incoming connections. func (server *HttpServer) ListenAndServe(addr string) error { @@ -121,6 +127,8 @@ func (server *HttpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { //针对websocket与调试信息特殊处理 if checkIsWebSocketRequest(req) { http.DefaultServeMux.ServeHTTP(w, req) + //增加状态计数 + core.GlobalState.AddRequestCount(req.URL.Path, defaultHttpCode, 1) } else { //设置header信息 w.Header().Set(HeaderServer, DefaultServerName) @@ -154,8 +162,8 @@ func (server *HttpServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { } } - //add view count with httpcode - core.GlobalState.AddTTPCodeCount(httpCtx.Request().Path(), httpCtx.Response().HttpCode(), 1) + //增加状态计数 + core.GlobalState.AddRequestCount(httpCtx.Request().Path(), httpCtx.Response().HttpCode(), 1) //release response response.release() @@ -182,28 +190,28 @@ func (server *HttpServer) SetOffline(offline bool, offlineText string, offlineUr // IndexPage default index page name func (server *HttpServer) IndexPage() string { - if server.ServerConfig.IndexPage == "" { + if server.ServerConfig().IndexPage == "" { return DefaultIndexPage } else { - return server.ServerConfig.IndexPage + return server.ServerConfig().IndexPage } } // SetSessionConfig set session store config func (server *HttpServer) SetSessionConfig(storeConfig *session.StoreConfig) { //sync session config - server.SessionConfig.Timeout = storeConfig.Maxlifetime - server.SessionConfig.SessionMode = storeConfig.StoreName - server.SessionConfig.ServerIP = storeConfig.ServerIP + server.SessionConfig().Timeout = storeConfig.Maxlifetime + server.SessionConfig().SessionMode = storeConfig.StoreName + server.SessionConfig().ServerIP = storeConfig.ServerIP logger.Logger().Debug("DotWeb:HttpServer SetSessionConfig ["+jsonutil.GetJsonString(storeConfig)+"]", LogTarget_HttpServer) } // InitSessionManager init session manager func (server *HttpServer) InitSessionManager() { storeConfig := new(session.StoreConfig) - storeConfig.Maxlifetime = server.SessionConfig.Timeout - storeConfig.StoreName = server.SessionConfig.SessionMode - storeConfig.ServerIP = server.SessionConfig.ServerIP + storeConfig.Maxlifetime = server.SessionConfig().Timeout + storeConfig.StoreName = server.SessionConfig().SessionMode + storeConfig.ServerIP = server.SessionConfig().ServerIP if server.sessionManager == nil { //设置Session @@ -226,7 +234,7 @@ func (server *HttpServer) setDotApp(dotApp *DotWeb) { // GetSessionManager get session manager in current httpserver func (server *HttpServer) GetSessionManager() *session.SessionManager { - if !server.SessionConfig.EnabledSession { + if !server.SessionConfig().EnabledSession { return nil } return server.sessionManager @@ -320,32 +328,32 @@ func (server *HttpServer) SetRenderer(r Renderer) { // SetEnabledAutoHEAD set EnabledAutoHEAD true or false func (server *HttpServer) SetEnabledAutoHEAD(autoHEAD bool) { - server.ServerConfig.EnabledAutoHEAD = autoHEAD + server.ServerConfig().EnabledAutoHEAD = autoHEAD logger.Logger().Debug("DotWeb:HttpServer SetEnabledAutoHEAD ["+strconv.FormatBool(autoHEAD)+"]", LogTarget_HttpServer) } // SetEnabledListDir 设置是否允许目录浏览,默认为false func (server *HttpServer) SetEnabledListDir(isEnabled bool) { - server.ServerConfig.EnabledListDir = isEnabled + server.ServerConfig().EnabledListDir = isEnabled logger.Logger().Debug("DotWeb:HttpServer SetEnabledListDir ["+strconv.FormatBool(isEnabled)+"]", LogTarget_HttpServer) } // SetEnabledSession 设置是否启用Session,默认为false func (server *HttpServer) SetEnabledSession(isEnabled bool) { - server.SessionConfig.EnabledSession = isEnabled + server.SessionConfig().EnabledSession = isEnabled logger.Logger().Debug("DotWeb:HttpServer SetEnabledSession ["+strconv.FormatBool(isEnabled)+"]", LogTarget_HttpServer) } // SetEnabledGzip 设置是否启用gzip,默认为false func (server *HttpServer) SetEnabledGzip(isEnabled bool) { - server.ServerConfig.EnabledGzip = isEnabled + server.ServerConfig().EnabledGzip = isEnabled logger.Logger().Debug("DotWeb:HttpServer SetEnabledGzip ["+strconv.FormatBool(isEnabled)+"]", LogTarget_HttpServer) } // SetEnabledIgnoreFavicon set IgnoreFavicon Enabled // default is false func (server *HttpServer) SetEnabledIgnoreFavicon(isEnabled bool) { - server.ServerConfig.EnabledIgnoreFavicon = isEnabled + server.ServerConfig().EnabledIgnoreFavicon = isEnabled logger.Logger().Debug("DotWeb:HttpServer SetEnabledIgnoreFavicon ["+strconv.FormatBool(isEnabled)+"]", LogTarget_HttpServer) server.RegisterModule(getIgnoreFaviconModule()) } @@ -354,12 +362,18 @@ func (server *HttpServer) SetEnabledIgnoreFavicon(isEnabled bool) { // default is false // if it's true, must input certificate\private key fileName func (server *HttpServer) SetEnabledTLS(isEnabled bool, certFile, keyFile string) { - server.ServerConfig.EnabledTLS = isEnabled - server.ServerConfig.TLSCertFile = certFile - server.ServerConfig.TLSKeyFile = keyFile + server.ServerConfig().EnabledTLS = isEnabled + server.ServerConfig().TLSCertFile = certFile + server.ServerConfig().TLSKeyFile = keyFile logger.Logger().Debug("DotWeb:HttpServer SetEnabledTLS ["+strconv.FormatBool(isEnabled)+","+certFile+","+keyFile+"]", LogTarget_HttpServer) } +// EnabledDetailRequestData 设置是否启用详细请求数据统计,默认为false +func (server *HttpServer) SetEnabledDetailRequestData(isEnabled bool) { + server.ServerConfig().EnabledDetailRequestData = isEnabled + logger.Logger().Debug("DotWeb:HttpServer SetEnabledDetailRequestData ["+strconv.FormatBool(isEnabled)+"]", LogTarget_HttpServer) +} + // RegisterModule 添加处理模块 func (server *HttpServer) RegisterModule(module *HttpModule) { server.Modules = append(server.Modules, module) diff --git a/version.MD b/version.MD index d88095e..0dbf050 100644 --- a/version.MD +++ b/version.MD @@ -1,5 +1,18 @@ ## dotweb版本记录: +#### Version 1.3.2 +* 主要新增设置启用详细请求数据控制,新增MethodNotAllowedHandler自定义能力,完善数据统计逻辑 +* 新增设置启用详细请求数据控制: +* 1) ServerStateInfo增加EnabledDetailRequestData,用于控制是否启用详细请求数据统计 +* 2) config.ServerConfig增加EnabledDetailRequestData设置,支持配置文件控制 +* 3) HttpServer增加SetEnabledDetailRequestData函数,用于代码设置是否启用详细请求数据统计 +* 4) fixed #63 状态数据,当url较多时,导致内存占用过大 +* 新增MethodNotAllowedHandler自定义能力 +* 1) dotweb增加DefaultMethodNotAllowedHandler、SetMethodNotAllowedHandle函数 +* 完善数据统计逻辑 +* 1) 404请求不计入详细请求数据统计 +* 2017-10-13 12:00 + #### Version 1.3.1 * 增加HttpServer.ServerFile,以支持server快捷设置静态文件目录 * 2017-10-11 22:00