From 22e1449284382bb957765178b029cb8c27bf9c12 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 20:40:11 +0700 Subject: [PATCH 01/10] app: remove interface and export struct --- README.md | 2 +- app.go | 49 ++++++++++------------- context.go | 6 +-- examples/net-http/main.go | 2 +- global.go | 6 ++- graceful.go | 24 +++++------ hime.go | 83 +-------------------------------------- route.go | 6 ++- template.go | 26 +++++++++--- 9 files changed, 68 insertions(+), 136 deletions(-) diff --git a/README.md b/README.md index 5a552f5..0d3b8f2 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ func main() { ListenAndServe(":8080") } -func router(app hime.App) http.Handler { +func router(app *hime.App) http.Handler { mux := http.NewServeMux() mux.Handle(app.Route("index"), hime.H(indexHandler)) return middleware.Chain( diff --git a/app.go b/app.go index c8bdfb8..8275afd 100644 --- a/app.go +++ b/app.go @@ -14,7 +14,8 @@ import ( "github.com/tdewolff/minify/js" ) -type app struct { +// App is the hime app +type App struct { srv *http.Server handler http.Handler templateFuncs []template.FuncMap @@ -44,8 +45,8 @@ func init() { } // New creates new app -func New() App { - app := &app{} +func New() *App { + app := &App{} app.template = make(map[string]*template.Template) app.templateRoot = defTemplateRoot app.templateDir = defTemplateDir @@ -54,26 +55,14 @@ func New() App { return app } -// TemplateRoot sets template root to select when load -func (app *app) TemplateRoot(name string) App { - app.templateRoot = name - return app -} - -// TemplateDir sets template dir -func (app *app) TemplateDir(path string) App { - app.templateDir = path - return app -} - -// Handler sets app handler -func (app *app) Handler(h http.Handler) App { +// Handler sets the handler +func (app *App) Handler(h http.Handler) *App { app.handler = h return app } -// Minify sets app minifier -func (app *app) Minify() App { +// Minify enables minify when render html, css, js +func (app *App) Minify() *App { app.minifier = minify.New() app.minifier.AddFunc("text/html", html.Minify) app.minifier.AddFunc("text/css", css.Minify) @@ -81,25 +70,28 @@ func (app *app) Minify() App { return app } -func (app *app) BeforeRender(m middleware.Middleware) App { +// BeforeRender runs given middleware for before render, +// ex. View, JSON, String, Bytes, CopyForm, etc +func (app *App) BeforeRender(m middleware.Middleware) *App { app.beforeRender = m return app } -func (app *app) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx := r.Context() ctx = context.WithValue(ctx, ctxKeyApp, app) r = r.WithContext(ctx) app.handler.ServeHTTP(w, r) } -func (app *app) Server(server *http.Server) App { +// Server overrides server when calling ListenAndServe +func (app *App) Server(server *http.Server) *App { app.srv = server return app } -// ListenAndServe is the shotcut for http.ListenAndServe -func (app *app) ListenAndServe(addr string) error { +// ListenAndServe starts web server +func (app *App) ListenAndServe(addr string) error { if app.srv == nil { app.srv = &http.Server{ Addr: addr, @@ -110,10 +102,11 @@ func (app *app) ListenAndServe(addr string) error { return app.srv.ListenAndServe() } -// GracefulShutdown change app to graceful mode -func (app *app) GracefulShutdown() GracefulShutdownApp { - return &gracefulShutdownApp{ - app: app, +// GracefulShutdown runs server as graceful shutdown, +// can works only when start server with app.ListenAndServe +func (app *App) GracefulShutdown() *GracefulShutdownApp { + return &GracefulShutdownApp{ + App: app, timeout: defShutdownTimeout, } } diff --git a/context.go b/context.go index 2bf14dc..19b82f3 100644 --- a/context.go +++ b/context.go @@ -11,21 +11,21 @@ func NewContext(w http.ResponseWriter, r *http.Request) Context { } func newInternalContext(w http.ResponseWriter, r *http.Request) *appContext { - app, ok := r.Context().Value(ctxKeyApp).(*app) + app, ok := r.Context().Value(ctxKeyApp).(*App) if !ok { panic(ErrAppNotFound) } return newContext(app, w, r) } -func newContext(app *app, w http.ResponseWriter, r *http.Request) *appContext { +func newContext(app *App, w http.ResponseWriter, r *http.Request) *appContext { return &appContext{r.Context(), app, r, w, 0} } type appContext struct { context.Context - app *app + app *App r *http.Request w http.ResponseWriter diff --git a/examples/net-http/main.go b/examples/net-http/main.go index 3309606..11f814b 100644 --- a/examples/net-http/main.go +++ b/examples/net-http/main.go @@ -51,7 +51,7 @@ func main() { } } -func router(app hime.App) http.Handler { +func router(app *hime.App) http.Handler { mux := http.NewServeMux() mux.Handle(app.Route("index"), hime.H(indexHandler)) mux.Handle(app.Route("about"), hime.H(aboutHandler)) diff --git a/global.go b/global.go index 31e775a..c18a8db 100644 --- a/global.go +++ b/global.go @@ -1,13 +1,15 @@ package hime -func (app *app) Globals(globals Globals) App { +// Globals registers global constants +func (app *App) Globals(globals Globals) *App { for key, value := range globals { app.globals[key] = value } return app } -func (app *app) Global(key interface{}) interface{} { +// Global gets value from global storage +func (app *App) Global(key interface{}) interface{} { return app.globals[key] } diff --git a/graceful.go b/graceful.go index c804b74..b9e9a89 100644 --- a/graceful.go +++ b/graceful.go @@ -9,43 +9,45 @@ import ( "time" ) -// GracefulShutdownApp - -type gracefulShutdownApp struct { - *app +// GracefulShutdownApp is the app in graceful shutdown mode +type GracefulShutdownApp struct { + *App timeout time.Duration wait time.Duration notiFns []func() beforeFns []func() } -// ShutdownTimeout sets shutdown timeout for graceful shutdown -func (app *gracefulShutdownApp) Timeout(d time.Duration) GracefulShutdownApp { +// Timeout sets shutdown timeout for graceful shutdown +func (app *GracefulShutdownApp) Timeout(d time.Duration) *GracefulShutdownApp { app.timeout = d return app } -func (app *gracefulShutdownApp) Wait(d time.Duration) GracefulShutdownApp { +// Wait sets wait time before shutdown +func (app *GracefulShutdownApp) Wait(d time.Duration) *GracefulShutdownApp { app.wait = d return app } -func (app *gracefulShutdownApp) Notify(fn func()) GracefulShutdownApp { +// Notify calls fn when receive terminate signal from os +func (app *GracefulShutdownApp) Notify(fn func()) *GracefulShutdownApp { if fn != nil { app.notiFns = append(app.notiFns, fn) } return app } -func (app *gracefulShutdownApp) Before(fn func()) GracefulShutdownApp { +// Before runs fn before start waiting to SIGTERM +func (app *GracefulShutdownApp) Before(fn func()) *GracefulShutdownApp { if fn != nil { app.beforeFns = append(app.beforeFns, fn) } return app } -// ListenAndServe is the shotcut for http.ListenAndServe -func (app *gracefulShutdownApp) ListenAndServe(addr string) (err error) { +// ListenAndServe starts web server in graceful shutdown mode +func (app *GracefulShutdownApp) ListenAndServe(addr string) (err error) { if app.srv == nil { app.srv = &http.Server{ Addr: addr, diff --git a/hime.go b/hime.go index fee2aa3..9e0cdd9 100644 --- a/hime.go +++ b/hime.go @@ -2,90 +2,12 @@ package hime import ( "context" - "html/template" "io" "mime/multipart" "net/http" "net/url" - "time" - - "github.com/acoshift/middleware" ) -// App is the hime app -type App interface { - http.Handler - - // Builder - - // TemplateDir sets directory to load template, - // default is "view" - TemplateDir(path string) App - - // TemplateRoot sets root layout using t.Lookup, - // default is "layout" - TemplateRoot(name string) App - - // TemplateFuncs adds template funcs while load template - TemplateFuncs(funcs ...template.FuncMap) App - - // Component adds given templates to every templates - Component(filename ...string) App - - // Template loads template into memory - Template(name string, filename ...string) App - - // BeforeRender runs given middleware for before render, - // ex. View, JSON, String, Bytes, CopyForm, etc. - BeforeRender(m middleware.Middleware) App - - // Minify enables minify when render html, css, js - Minify() App - - // Handler sets the handler - Handler(h http.Handler) App - - // Routes registers route name and path - Routes(routes Routes) App - - // Globals registers global constants - Globals(Globals) App - - // Server overrides server when calling ListenAndServe - Server(server *http.Server) App - - // GracefulShutdown runs server as graceful shutdown, - // can works only when start server with app.ListenAndServe - GracefulShutdown() GracefulShutdownApp - - // ListenAndServe starts web server - ListenAndServe(addr string) error - - // Route gets route path from given name - Route(name string, params ...interface{}) string - - // Global gets value from global storage - Global(key interface{}) interface{} -} - -// GracefulShutdownApp is the app in graceful shutdown mode -type GracefulShutdownApp interface { - // Timeout sets timeout - Timeout(d time.Duration) GracefulShutdownApp - - // Wait sets wait time before shutdown - Wait(d time.Duration) GracefulShutdownApp - - // Notify calls fn when receive terminate signal from os - Notify(fn func()) GracefulShutdownApp - - // Before runs fn before start waiting to SIGTERM - Before(fn func()) GracefulShutdownApp - - // ListenAndServe starts web server - ListenAndServe(addr string) error -} - // Routes is the map for route name => path type Routes map[string]string @@ -227,7 +149,4 @@ type Param struct { Value interface{} } -var ( - _ = App(&app{}) - _ = Context(&appContext{}) -) +var _ = Context(&appContext{}) diff --git a/route.go b/route.go index fbd8080..7f3488c 100644 --- a/route.go +++ b/route.go @@ -1,13 +1,15 @@ package hime -func (app *app) Routes(routes Routes) App { +// Routes registers route name and path +func (app *App) Routes(routes Routes) *App { for name, path := range routes { app.routes[name] = path } return app } -func (app *app) Route(name string, params ...interface{}) string { +// Route gets route path from given name +func (app *App) Route(name string, params ...interface{}) string { path, ok := app.routes[name] if !ok { panic(newErrRouteNotFound(name)) diff --git a/template.go b/template.go index 94dfa5a..e5ebbc1 100644 --- a/template.go +++ b/template.go @@ -5,20 +5,34 @@ import ( "path/filepath" ) -// TemplateFuncs adds template funcs -func (app *app) TemplateFuncs(funcs ...template.FuncMap) App { +// TemplateRoot sets root layout using t.Lookup, +// default is "layout" +func (app *App) TemplateRoot(name string) *App { + app.templateRoot = name + return app +} + +// TemplateDir sets directory to load template, +// default is "view" +func (app *App) TemplateDir(path string) *App { + app.templateDir = path + return app +} + +// TemplateFuncs adds template funcs while load template +func (app *App) TemplateFuncs(funcs ...template.FuncMap) *App { app.templateFuncs = append(app.templateFuncs, funcs...) return app } -// Component adds global template component -func (app *app) Component(filename ...string) App { +// Component adds given templates to every templates +func (app *App) Component(filename ...string) *App { app.templateComponents = append(app.templateComponents, filename...) return app } -// Template registers new template -func (app *app) Template(name string, filename ...string) App { +// Template loads template into memory +func (app *App) Template(name string, filename ...string) *App { if _, ok := app.template[name]; ok { panic(newErrTemplateDuplicate(name)) } From d39e902452cfccd03ac7b56fa2039bf7fdd04842 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 21:19:33 +0700 Subject: [PATCH 02/10] init globals and routes when load --- app.go | 2 -- global.go | 6 ++++++ route.go | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app.go b/app.go index 8275afd..4083098 100644 --- a/app.go +++ b/app.go @@ -50,8 +50,6 @@ func New() *App { app.template = make(map[string]*template.Template) app.templateRoot = defTemplateRoot app.templateDir = defTemplateDir - app.routes = make(Routes) - app.globals = make(Globals) return app } diff --git a/global.go b/global.go index c18a8db..549cebb 100644 --- a/global.go +++ b/global.go @@ -2,6 +2,9 @@ package hime // Globals registers global constants func (app *App) Globals(globals Globals) *App { + if app.globals == nil { + app.globals = make(Globals) + } for key, value := range globals { app.globals[key] = value } @@ -10,6 +13,9 @@ func (app *App) Globals(globals Globals) *App { // Global gets value from global storage func (app *App) Global(key interface{}) interface{} { + if app.globals == nil { + return nil + } return app.globals[key] } diff --git a/route.go b/route.go index 7f3488c..fed6b33 100644 --- a/route.go +++ b/route.go @@ -2,6 +2,9 @@ package hime // Routes registers route name and path func (app *App) Routes(routes Routes) *App { + if app.routes == nil { + app.routes = make(Routes) + } for name, path := range routes { app.routes[name] = path } @@ -10,6 +13,9 @@ func (app *App) Routes(routes Routes) *App { // Route gets route path from given name func (app *App) Route(name string, params ...interface{}) string { + if app.routes == nil { + panic(newErrRouteNotFound(name)) + } path, ok := app.routes[name] if !ok { panic(newErrRouteNotFound(name)) From 68e7ef415bb4d7f2348afd26b54981abcde895bf Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 21:28:11 +0700 Subject: [PATCH 03/10] move init value out from New --- app.go | 8 +------- template.go | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app.go b/app.go index 4083098..ace5f43 100644 --- a/app.go +++ b/app.go @@ -31,8 +31,6 @@ type App struct { // consts const ( - defTemplateRoot = "layout" - defTemplateDir = "view" defShutdownTimeout = 30 * time.Second ) @@ -46,11 +44,7 @@ func init() { // New creates new app func New() *App { - app := &App{} - app.template = make(map[string]*template.Template) - app.templateRoot = defTemplateRoot - app.templateDir = defTemplateDir - return app + return &App{} } // Handler sets the handler diff --git a/template.go b/template.go index e5ebbc1..013c9b2 100644 --- a/template.go +++ b/template.go @@ -5,15 +5,18 @@ import ( "path/filepath" ) -// TemplateRoot sets root layout using t.Lookup, -// default is "layout" +// TemplateRoot calls t.Lookup(name) after load template, +// empty string won't trigger t.Lookup +// +// default is "" func (app *App) TemplateRoot(name string) *App { app.templateRoot = name return app } -// TemplateDir sets directory to load template, -// default is "view" +// TemplateDir sets root directory when load template +// +// default is "" func (app *App) TemplateDir(path string) *App { app.templateDir = path return app @@ -33,6 +36,10 @@ func (app *App) Component(filename ...string) *App { // Template loads template into memory func (app *App) Template(name string, filename ...string) *App { + if app.template == nil { + app.template = make(map[string]*template.Template) + } + if _, ok := app.template[name]; ok { panic(newErrTemplateDuplicate(name)) } @@ -59,8 +66,12 @@ func (app *App) Template(name string, filename ...string) *App { fn := make([]string, len(filename)) copy(fn, filename) fn = append(fn, app.templateComponents...) + t = template.Must(t.ParseFiles(joinTemplateDir(app.templateDir, fn...)...)) - t = t.Lookup(app.templateRoot) + + if app.templateRoot != "" { + t = t.Lookup(app.templateRoot) + } app.template[name] = t From 5e18feb3256852c0531ae70038b6722d23e85a54 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 21:33:45 +0700 Subject: [PATCH 04/10] remove default graceful shutdown timeout --- README.md | 2 +- app.go | 9 +-------- graceful.go | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0d3b8f2..4985018 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Other framework don't allow this. They have built-in router, framework-specific - Compatible with net/http middlewares without code change - Use standard html/template for view - Built-in core functions for build web server -- Reduce developer bug +- Reduce developer bugs ## What is this framework DO NOT focus diff --git a/app.go b/app.go index ace5f43..f2775e5 100644 --- a/app.go +++ b/app.go @@ -5,7 +5,6 @@ import ( "html/template" "mime" "net/http" - "time" "github.com/acoshift/middleware" "github.com/tdewolff/minify" @@ -29,11 +28,6 @@ type App struct { beforeRender middleware.Middleware } -// consts -const ( - defShutdownTimeout = 30 * time.Second -) - var ( ctxKeyApp = struct{}{} ) @@ -98,7 +92,6 @@ func (app *App) ListenAndServe(addr string) error { // can works only when start server with app.ListenAndServe func (app *App) GracefulShutdown() *GracefulShutdownApp { return &GracefulShutdownApp{ - App: app, - timeout: defShutdownTimeout, + App: app, } } diff --git a/graceful.go b/graceful.go index b9e9a89..55e0128 100644 --- a/graceful.go +++ b/graceful.go @@ -18,7 +18,10 @@ type GracefulShutdownApp struct { beforeFns []func() } -// Timeout sets shutdown timeout for graceful shutdown +// Timeout sets shutdown timeout for graceful shutdown, +// set to 0 to disable timeout +// +// default is 0 func (app *GracefulShutdownApp) Timeout(d time.Duration) *GracefulShutdownApp { app.timeout = d return app @@ -80,9 +83,14 @@ func (app *GracefulShutdownApp) ListenAndServe(addr string) (err error) { if app.wait > 0 { time.Sleep(app.wait) } - ctx, cancel := context.WithTimeout(context.Background(), app.timeout) - defer cancel() - err = app.srv.Shutdown(ctx) + + if app.timeout > 0 { + ctx, cancel := context.WithTimeout(context.Background(), app.timeout) + defer cancel() + err = app.srv.Shutdown(ctx) + } else { + err = app.srv.Shutdown(context.Background()) + } } return } From 38f6abc5c643d34c33be80bf3b49d12fd896c47e Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 22:06:09 +0700 Subject: [PATCH 05/10] graceful shutdown don't embeded app --- app.go | 7 +++---- graceful.go | 56 ++++++++++++++++++++++++++--------------------------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/app.go b/app.go index f2775e5..a6b1eb4 100644 --- a/app.go +++ b/app.go @@ -88,10 +88,9 @@ func (app *App) ListenAndServe(addr string) error { return app.srv.ListenAndServe() } -// GracefulShutdown runs server as graceful shutdown, -// can works only when start server with app.ListenAndServe -func (app *App) GracefulShutdown() *GracefulShutdownApp { - return &GracefulShutdownApp{ +// GracefulShutdown returns graceful shutdown server +func (app *App) GracefulShutdown() *GracefulShutdown { + return &GracefulShutdown{ App: app, } } diff --git a/graceful.go b/graceful.go index 55e0128..00043bd 100644 --- a/graceful.go +++ b/graceful.go @@ -9,9 +9,9 @@ import ( "time" ) -// GracefulShutdownApp is the app in graceful shutdown mode -type GracefulShutdownApp struct { - *App +// GracefulShutdown is the app in graceful shutdown mode +type GracefulShutdown struct { + App *App timeout time.Duration wait time.Duration notiFns []func() @@ -22,51 +22,51 @@ type GracefulShutdownApp struct { // set to 0 to disable timeout // // default is 0 -func (app *GracefulShutdownApp) Timeout(d time.Duration) *GracefulShutdownApp { - app.timeout = d - return app +func (gs *GracefulShutdown) Timeout(d time.Duration) *GracefulShutdown { + gs.timeout = d + return gs } // Wait sets wait time before shutdown -func (app *GracefulShutdownApp) Wait(d time.Duration) *GracefulShutdownApp { - app.wait = d - return app +func (gs *GracefulShutdown) Wait(d time.Duration) *GracefulShutdown { + gs.wait = d + return gs } // Notify calls fn when receive terminate signal from os -func (app *GracefulShutdownApp) Notify(fn func()) *GracefulShutdownApp { +func (gs *GracefulShutdown) Notify(fn func()) *GracefulShutdown { if fn != nil { - app.notiFns = append(app.notiFns, fn) + gs.notiFns = append(gs.notiFns, fn) } - return app + return gs } // Before runs fn before start waiting to SIGTERM -func (app *GracefulShutdownApp) Before(fn func()) *GracefulShutdownApp { +func (gs *GracefulShutdown) Before(fn func()) *GracefulShutdown { if fn != nil { - app.beforeFns = append(app.beforeFns, fn) + gs.beforeFns = append(gs.beforeFns, fn) } - return app + return gs } // ListenAndServe starts web server in graceful shutdown mode -func (app *GracefulShutdownApp) ListenAndServe(addr string) (err error) { - if app.srv == nil { - app.srv = &http.Server{ +func (gs *GracefulShutdown) ListenAndServe(addr string) (err error) { + if gs.App.srv == nil { + gs.App.srv = &http.Server{ Addr: addr, - Handler: app, + Handler: gs.App, } } serverCtx, cancelServer := context.WithCancel(context.Background()) defer cancelServer() go func() { - if err = app.srv.ListenAndServe(); err != http.ErrServerClosed { + if err = gs.App.srv.ListenAndServe(); err != http.ErrServerClosed { cancelServer() } }() - for _, fn := range app.beforeFns { + for _, fn := range gs.beforeFns { fn() } @@ -77,19 +77,19 @@ func (app *GracefulShutdownApp) ListenAndServe(addr string) (err error) { case <-serverCtx.Done(): return case <-stop: - for _, fn := range app.notiFns { + for _, fn := range gs.notiFns { fn() } - if app.wait > 0 { - time.Sleep(app.wait) + if gs.wait > 0 { + time.Sleep(gs.wait) } - if app.timeout > 0 { - ctx, cancel := context.WithTimeout(context.Background(), app.timeout) + if gs.timeout > 0 { + ctx, cancel := context.WithTimeout(context.Background(), gs.timeout) defer cancel() - err = app.srv.Shutdown(ctx) + err = gs.App.srv.Shutdown(ctx) } else { - err = app.srv.Shutdown(context.Background()) + err = gs.App.srv.Shutdown(context.Background()) } } return From bfb9609347e2a91a9c2a43fc02f0661467a20fb1 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 22:45:59 +0700 Subject: [PATCH 06/10] add server config to app --- app.go | 72 +++++++++++++++++++++++++++++++++++++++++++++-------- graceful.go | 22 ++++++++-------- 2 files changed, 74 insertions(+), 20 deletions(-) diff --git a/app.go b/app.go index a6b1eb4..43df29c 100644 --- a/app.go +++ b/app.go @@ -2,9 +2,13 @@ package hime import ( "context" + "crypto/tls" "html/template" + "log" "mime" + "net" "net/http" + "time" "github.com/acoshift/middleware" "github.com/tdewolff/minify" @@ -15,7 +19,37 @@ import ( // App is the hime app type App struct { - srv *http.Server + // Addr listens address + Addr string + + // TLSConfig overrides http.Server TLSConfig + TLSConfig *tls.Config + + // ReadTimeout overrides http.Server ReadTimeout + ReadTimeout time.Duration + + // ReadHeaderTimeout overrides http.Server ReadHeaderTimeout + ReadHeaderTimeout time.Duration + + // WriteTimeout overrides http.Server WriteTimeout + WriteTimeout time.Duration + + // IdleTimeout overrides http.Server IdleTimeout + IdleTimeout time.Duration + + // MaxHeaderBytes overrides http.Server MaxHeaderBytes + MaxHeaderBytes int + + // TLSNextProto overrides http.Server TLSNextProto + TLSNextProto map[string]func(*http.Server, *tls.Conn, http.Handler) + + // ConnState overrides http.Server ConnState + ConnState func(net.Conn, http.ConnState) + + // ErrorLog overrides http.Server ErrorLog + ErrorLog *log.Logger + + srv http.Server handler http.Handler templateFuncs []template.FuncMap templateComponents []string @@ -70,24 +104,42 @@ func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { app.handler.ServeHTTP(w, r) } -// Server overrides server when calling ListenAndServe -func (app *App) Server(server *http.Server) *App { - app.srv = server - return app +func (app *App) configServer() { + app.srv.Addr = app.Addr + app.srv.TLSConfig = app.TLSConfig + app.srv.ReadTimeout = app.ReadTimeout + app.srv.ReadHeaderTimeout = app.ReadHeaderTimeout + app.srv.WriteTimeout = app.WriteTimeout + app.srv.IdleTimeout = app.IdleTimeout + app.srv.MaxHeaderBytes = app.MaxHeaderBytes + app.srv.TLSNextProto = app.TLSNextProto + app.srv.ConnState = app.ConnState + app.srv.ErrorLog = app.ErrorLog + app.srv.Handler = app } // ListenAndServe starts web server func (app *App) ListenAndServe(addr string) error { - if app.srv == nil { - app.srv = &http.Server{ - Addr: addr, - Handler: app, - } + app.configServer() + + if addr != "" { + app.srv.Addr = addr } return app.srv.ListenAndServe() } +// ListenAndServeTLS starts web server in tls mode +func (app *App) ListenAndServeTLS(addr, certFile, keyFile string) error { + app.configServer() + + if addr != "" { + app.srv.Addr = addr + } + + return app.srv.ListenAndServeTLS(certFile, keyFile) +} + // GracefulShutdown returns graceful shutdown server func (app *App) GracefulShutdown() *GracefulShutdown { return &GracefulShutdown{ diff --git a/graceful.go b/graceful.go index 00043bd..5be8da5 100644 --- a/graceful.go +++ b/graceful.go @@ -49,19 +49,11 @@ func (gs *GracefulShutdown) Before(fn func()) *GracefulShutdown { return gs } -// ListenAndServe starts web server in graceful shutdown mode -func (gs *GracefulShutdown) ListenAndServe(addr string) (err error) { - if gs.App.srv == nil { - gs.App.srv = &http.Server{ - Addr: addr, - Handler: gs.App, - } - } - +func (gs *GracefulShutdown) start(listenAndServe func() error) (err error) { serverCtx, cancelServer := context.WithCancel(context.Background()) defer cancelServer() go func() { - if err = gs.App.srv.ListenAndServe(); err != http.ErrServerClosed { + if err = listenAndServe(); err != http.ErrServerClosed { cancelServer() } }() @@ -94,3 +86,13 @@ func (gs *GracefulShutdown) ListenAndServe(addr string) (err error) { } return } + +// ListenAndServe starts web server in graceful shutdown mode +func (gs *GracefulShutdown) ListenAndServe(addr string) error { + return gs.start(func() error { return gs.App.ListenAndServe(addr) }) +} + +// ListenAndServeTLS starts web server in graceful shutdown and tls mode +func (gs *GracefulShutdown) ListenAndServeTLS(addr, certFile, keyFile string) error { + return gs.start(func() error { return gs.App.ListenAndServeTLS(addr, certFile, keyFile) }) +} From 4d40cea696e0d5590fff620bd5c94a1d630996d0 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 23:33:39 +0700 Subject: [PATCH 07/10] remove Addr from App --- app.go | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index 43df29c..46a2d16 100644 --- a/app.go +++ b/app.go @@ -19,9 +19,6 @@ import ( // App is the hime app type App struct { - // Addr listens address - Addr string - // TLSConfig overrides http.Server TLSConfig TLSConfig *tls.Config @@ -104,8 +101,7 @@ func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { app.handler.ServeHTTP(w, r) } -func (app *App) configServer() { - app.srv.Addr = app.Addr +func (app *App) configServer(addr string) { app.srv.TLSConfig = app.TLSConfig app.srv.ReadTimeout = app.ReadTimeout app.srv.ReadHeaderTimeout = app.ReadHeaderTimeout @@ -116,26 +112,19 @@ func (app *App) configServer() { app.srv.ConnState = app.ConnState app.srv.ErrorLog = app.ErrorLog app.srv.Handler = app + app.srv.Addr = addr } // ListenAndServe starts web server func (app *App) ListenAndServe(addr string) error { - app.configServer() - - if addr != "" { - app.srv.Addr = addr - } + app.configServer(addr) return app.srv.ListenAndServe() } // ListenAndServeTLS starts web server in tls mode func (app *App) ListenAndServeTLS(addr, certFile, keyFile string) error { - app.configServer() - - if addr != "" { - app.srv.Addr = addr - } + app.configServer(addr) return app.srv.ListenAndServeTLS(certFile, keyFile) } From 0f8b6623747fbb03f8712428502579f56a900777 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 23:36:43 +0700 Subject: [PATCH 08/10] add travis --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ce4f6b9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - 1.9.x + - 1.10.x + +before_install: + - go get github.com/mattn/goveralls + +script: + - $HOME/gopath/bin/goveralls -service=travis-ci From 9a7d640f20076a0b3c39e036853e84c3f86a785f Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 23:39:32 +0700 Subject: [PATCH 09/10] add badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4985018..f45de2c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Hime +[![Build Status](https://travis-ci.org/acoshift/hime.svg?branch=master)](https://travis-ci.org/acoshift/hime) +[![Coverage Status](https://coveralls.io/repos/github/acoshift/hime/badge.svg?branch=master)](https://coveralls.io/github/acoshift/hime?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/acoshift/hime)](https://goreportcard.com/report/github.com/acoshift/hime) [![GoDoc](https://godoc.org/github.com/acoshift/hime?status.svg)](https://godoc.org/github.com/acoshift/hime) From 7dab9a0906f024b5cbcd95558979765629139ad3 Mon Sep 17 00:00:00 2001 From: acoshift Date: Mon, 14 May 2018 23:43:13 +0700 Subject: [PATCH 10/10] update .travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ce4f6b9..5b98bb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,5 @@ before_install: - go get github.com/mattn/goveralls script: - - $HOME/gopath/bin/goveralls -service=travis-ci + - go test -v -covermode=count -coverprofile=profile.cov . + - $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci