diff --git a/config/configs.go b/config/configs.go index 1cb8134..1b951c1 100644 --- a/config/configs.go +++ b/config/configs.go @@ -7,6 +7,7 @@ import ( "github.com/devfeel/dotweb/core" "github.com/devfeel/dotweb/framework/file" "io/ioutil" + //"time" ) type ( @@ -46,6 +47,7 @@ type ( EnabledAutoHEAD bool `xml:"enabledautohead,attr"` //设置是否自动启用Head路由,若设置该项,则会为除Websocket\HEAD外所有路由方式默认添加HEAD路由,默认不开启 EnabledAutoCORS bool `xml:"enabledautocors,attr"` //设置是否自动跨域支持,若设置,默认“GET, POST, PUT, DELETE, OPTIONS”全部请求均支持跨域 Port int `xml:"port,attr"` //端口 + RequestTimeOut int `xml:"requestrimeout,attr"` //请求超时时间,单位毫秒,默认30000秒 } SessionNode struct { @@ -180,9 +182,18 @@ func InitConfig(configFile string, confType ...interface{}) (config *Config, err } config.AppSetConfig = tmpAppSetMap + //deal config default value + dealConfigDefaultSet(config) + return config, nil } +func dealConfigDefaultSet(c *Config) { + if c.Server.RequestTimeOut <= 0 { + c.Server.RequestTimeOut = DefaultRequestTimeOut + } +} + //初始化配置文件(xml) func initXmlConfig(configFile string) (*Config, error) { content, err := ioutil.ReadFile(configFile) diff --git a/config/defaults.go b/config/defaults.go new file mode 100644 index 0000000..df03187 --- /dev/null +++ b/config/defaults.go @@ -0,0 +1,7 @@ +package config + +const ( + + //default timeout Millisecond for per request handler + DefaultRequestTimeOut = 30000 +) diff --git a/context.go b/context.go index 13cdeb9..7aa4cee 100644 --- a/context.go +++ b/context.go @@ -6,6 +6,7 @@ import ( "net/http" "net/url" + "context" "fmt" "github.com/devfeel/dotweb/cache" "github.com/devfeel/dotweb/core" @@ -20,6 +21,8 @@ const ( type ( Context interface { + Context() context.Context + Cancle() HttpServer() *HttpServer Response() *Response Request() *Request @@ -68,6 +71,8 @@ type ( } HttpContext struct { + context context.Context + cancle context.CancelFunc request *Request routerNode RouterNode routerParams Params @@ -123,6 +128,14 @@ func (ctx *HttpContext) release() { ctx.startTime = time.Time{} } +func (ctx *HttpContext) Context() context.Context { + return ctx.context +} + +func (ctx *HttpContext) Cancle() { + ctx.cancle() +} + func (ctx *HttpContext) HttpServer() *HttpServer { return ctx.httpServer } diff --git a/dotweb.go b/dotweb.go index 63f94ea..56512aa 100644 --- a/dotweb.go +++ b/dotweb.go @@ -268,38 +268,10 @@ func (app *DotWeb) SetConfig(config *config.Config) error { return nil } -/*启动WebServer -* 需要初始化HttpRoute -* httpPort := 80 - */ +// StartServer start server with http port +// if config the pprof, will be start pprof server func (app *DotWeb) StartServer(httpport int) error { - initInnerRouter(app.HttpServer) - - if app.ExceptionHandler == nil { - app.SetExceptionHandle(app.DefaultHTTPErrorHandler) - } - - //init session manager - 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()) - } - app.HttpServer.InitSessionManager() - } - - //if cache not set, create default runtime cache - if app.Cache() == nil { - app.cache = cache.NewRuntimeCache() - } - - //if renderer not set, create inner renderer - if app.HttpServer.Renderer() == nil { - app.HttpServer.SetRenderer(NewInnerRenderer()) - } - //start pprof server if app.Config.App.EnabledPProf { if app.Config.App.PProfPort == httpport { @@ -318,11 +290,9 @@ func (app *DotWeb) StartServer(httpport int) error { //add default httphandler with middlewares app.Use(&xMiddleware{}) + addr := ":" + strconv.Itoa(httpport) + return app.ListenAndServe(addr) - port := ":" + strconv.Itoa(httpport) - logger.Logger().Log("Dotweb:StartServer["+port+"] begin", LogTarget_HttpServer, LogLevel_Debug) - err := http.ListenAndServe(port, app.HttpServer) - return err } // Start start app server with set config @@ -350,6 +320,39 @@ func (app *DotWeb) MustStart() { } } +// ListenAndServe start server with addr +func (app *DotWeb) ListenAndServe(addr string) error { + initInnerRouter(app.HttpServer) + + if app.ExceptionHandler == nil { + app.SetExceptionHandle(app.DefaultHTTPErrorHandler) + } + + //init session manager + 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()) + } + app.HttpServer.InitSessionManager() + } + + //if cache not set, create default runtime cache + if app.Cache() == nil { + app.cache = cache.NewRuntimeCache() + } + + //if renderer not set, create inner renderer + if app.HttpServer.Renderer() == nil { + app.HttpServer.SetRenderer(NewInnerRenderer()) + } + + logger.Logger().Log("Dotweb:ListenAndServe["+addr+"] begin", LogTarget_HttpServer, LogLevel_Debug) + err := http.ListenAndServe(addr, app.HttpServer) + return err +} + // StartServerWithConfig start server with config func (app *DotWeb) StartServerWithConfig(config *config.Config) error { err := app.SetConfig(config) @@ -379,7 +382,7 @@ func (ds *DotWeb) DefaultHTTPErrorHandler(ctx Context, err error) { } } -//添加框架内部路由规则 +// init inner routers func initInnerRouter(server *HttpServer) { //默认支持pprof信息查看 gInner := server.Group("/dotweb") diff --git a/example/httpmodule/main.go b/example/httpmodule/main.go index 0103d93..7584538 100644 --- a/example/httpmodule/main.go +++ b/example/httpmodule/main.go @@ -1,11 +1,14 @@ package main import ( + "context" + "errors" "fmt" "github.com/devfeel/dotweb" "github.com/devfeel/dotweb/framework/file" "github.com/devfeel/dotweb/session" "strconv" + "time" ) func main() { @@ -31,7 +34,7 @@ func main() { InitRoute(app.HttpServer) //设置HttpModule - InitModule(app) + //InitModule(app) //启动 监控服务 //app.SetPProfConfig(true, 8081) @@ -40,6 +43,8 @@ func main() { app.AppContext.Set("gstring", "gvalue") app.AppContext.Set("gint", 1) + app.HttpServer.ServerConfig.RequestTimeOut = 2000 + // 开始服务 port := 8080 fmt.Println("dotweb.StartServer => " + strconv.Itoa(port)) @@ -54,11 +59,32 @@ func Index(ctx dotweb.Context) error { return err } +func CtxTimeOut(ctx dotweb.Context) error { + fmt.Println(sleep(ctx.Context())) + return nil +} + +func sleep(runCtx context.Context) error { + c := make(chan error, 1) + go func() { + time.Sleep(time.Second * 10) + fmt.Println("sleep time end") + c <- errors.New("test") + }() + select { + case <-runCtx.Done(): + return runCtx.Err() + case err := <-c: + return err + } +} + func InitRoute(server *dotweb.HttpServer) { - server.Router().GET("/", Index) - server.Router().GET("/user", Index) //need login - server.Router().GET("/login", Index) - server.Router().GET("/reg", Index) + server.GET("/", Index) + server.GET("/user", Index) //need login + server.GET("/login", Index) + server.GET("/reg", Index) + server.GET("/ctx", CtxTimeOut) } func InitModule(dotserver *dotweb.DotWeb) { diff --git a/server.go b/server.go index 31f30f1..6cf8014 100644 --- a/server.go +++ b/server.go @@ -13,6 +13,7 @@ import ( "time" "compress/gzip" + "context" "github.com/devfeel/dotweb/config" "github.com/devfeel/dotweb/feature" "github.com/devfeel/dotweb/logger" @@ -283,6 +284,7 @@ func (server *HttpServer) wrapRouterHandle(handler HttpHandle, isHijack bool) Ro req.reset(r) httpCtx := server.pool.context.Get().(*HttpContext) httpCtx.reset(res, req, server, vnode.Node, vnode.Params, handler) + httpCtx.context, httpCtx.cancle = context.WithTimeout(context.Background(), time.Duration(server.ServerConfig.RequestTimeOut)*time.Millisecond) //gzip if server.ServerConfig.EnabledGzip { @@ -359,6 +361,10 @@ func (server *HttpServer) wrapRouterHandle(handler HttpHandle, isHijack bool) Ro w = res.Writer().(*gzipResponseWriter).Writer w.(*gzip.Writer).Close() } + + //cancle Context + httpCtx.Cancle() + //release response res.release() server.pool.response.Put(res) diff --git a/version.MD b/version.MD index 61f21f8..3358c6d 100644 --- a/version.MD +++ b/version.MD @@ -1,5 +1,16 @@ ##dotweb版本记录: +#### Version 0.3.21 +* 新增HttpServer.ListenAndServer(addr string) 支持原生host监听 +* Context增加Context() & Cancle() 以通过context.Context实现请求超时机制 +* 配置文件Server节点增加RequestTimeOut设置,表示请求超时时间,单位毫秒,默认30000秒 +* 2017-06-14 06:30 + +#### Version 0.3.20 +* 新增Gzip中间件,参考https://github.com/devfeel/middleware/tree/master/gzip +* 统一:所有中间件的New方式统一为package.Middleware() +* 2017-06-11 17:00 + #### Version 0.3.19 * 新增AccessLog中间件,参考https://github.com/devfeel/middleware/tree/master/accesslog * use dotweb.logger