123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- package mhayaGin
- import (
- "context"
- "net/http"
- "time"
- "github.com/gin-gonic/gin"
- cfile "github.com/mhaya/extend/file"
- cfacade "github.com/mhaya/facade"
- clog "github.com/mhaya/logger"
- )
- type (
- OptionFunc func(opts *Options)
- // Options http server parameter
- Options struct {
- ReadTimeout time.Duration
- ReadHeaderTimeout time.Duration
- WriteTimeout time.Duration
- IdleTimeout time.Duration
- MaxHeaderBytes int
- CertFile string
- KeyFile string
- }
- HttpServer struct {
- cfacade.IApplication
- Options
- *gin.Engine
- server *http.Server
- controllers []IController
- }
- )
- func init() {
- SetMode(gin.ReleaseMode)
- }
- func SetMode(value string) {
- gin.SetMode(value)
- }
- func NewHttpServer(address string, opts ...OptionFunc) *HttpServer {
- if address == "" {
- clog.Error("listener address is empty.")
- return nil
- }
- httpServer := &HttpServer{
- Engine: gin.New(),
- }
- httpServer.server = &http.Server{
- Addr: address,
- Handler: httpServer.Engine,
- }
- httpServer.server.Handler = http.AllowQuerySemicolons(httpServer.server.Handler)
- httpServer.Options = defaultOptions()
- for _, opt := range opts {
- opt(&httpServer.Options)
- }
- return httpServer
- }
- func defaultOptions() Options {
- return Options{
- ReadTimeout: 0,
- ReadHeaderTimeout: 0,
- WriteTimeout: 0,
- IdleTimeout: 0,
- MaxHeaderBytes: 0,
- CertFile: "",
- KeyFile: "",
- }
- }
- func (p *HttpServer) Use(middleware ...GinHandlerFunc) {
- p.Engine.Use(BindHandlers(middleware)...)
- }
- func (p *HttpServer) SetIApplication(app cfacade.IApplication) {
- p.IApplication = app
- }
- func (p *HttpServer) Register(controllers ...IController) *HttpServer {
- p.controllers = append(p.controllers, controllers...)
- return p
- }
- func (p *HttpServer) Static(relativePath string, staticDir string) {
- dir, ok := cfile.JudgePath(staticDir)
- if !ok {
- clog.Errorf("static dir path not found. staticDir = %s", staticDir)
- return
- }
- p.Engine.StaticFS(relativePath, http.Dir(dir))
- }
- func (p *HttpServer) StaticFile(relativePath, filepath string) {
- dir, ok := cfile.JudgeFile(filepath)
- if !ok {
- clog.Errorf("static dir path not found. filePath = %s", filepath)
- return
- }
- p.Engine.StaticFile(relativePath, dir)
- }
- func (p *HttpServer) Run() {
- if p.server.Addr == "" {
- clog.Warn("no set listener address.")
- return
- }
- if p.Options.ReadTimeout > 0 {
- p.server.ReadTimeout = p.Options.ReadTimeout
- }
- if p.Options.ReadHeaderTimeout > 0 {
- p.server.ReadHeaderTimeout = p.Options.ReadHeaderTimeout
- }
- if p.Options.WriteTimeout > 0 {
- p.server.WriteTimeout = p.Options.WriteTimeout
- }
- if p.Options.IdleTimeout > 0 {
- p.server.IdleTimeout = p.Options.IdleTimeout
- }
- if p.Options.MaxHeaderBytes > 0 {
- p.server.MaxHeaderBytes = p.Options.MaxHeaderBytes
- }
- for _, controller := range p.controllers {
- controller.PreInit(p.IApplication, p.Engine)
- controller.Init()
- }
- p.listener()
- }
- func (p *HttpServer) listener() {
- var err error
- if p.Options.CertFile != "" && p.Options.KeyFile != "" {
- clog.Infof("https run. https://%s, certFile = %s, keyFile = %s",
- p.server.Addr, p.Options.CertFile, p.Options.KeyFile)
- err = p.server.ListenAndServeTLS(p.Options.CertFile, p.Options.KeyFile)
- } else {
- clog.Infof("http run. http://%s", p.server.Addr)
- err = p.server.ListenAndServe()
- }
- if err != http.ErrServerClosed {
- clog.Infof("run error = %s", err)
- }
- }
- func (p *HttpServer) Stop() {
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- for _, controller := range p.controllers {
- controller.Stop()
- }
- if err := p.server.Shutdown(ctx); err != nil {
- clog.Info(err.Error())
- }
- clog.Infof("shutdown http server on %s", p.server.Addr)
- }
- func WithReadTimeout(t time.Duration) OptionFunc {
- return func(opts *Options) {
- opts.ReadTimeout = t
- }
- }
- func WithReadHeaderTimeout(t time.Duration) OptionFunc {
- return func(opts *Options) {
- opts.ReadHeaderTimeout = t
- }
- }
- func WithIdleTimeout(t time.Duration) OptionFunc {
- return func(opts *Options) {
- opts.IdleTimeout = t
- }
- }
- func WithMaxHeaderBytes(val int) OptionFunc {
- return func(opts *Options) {
- opts.MaxHeaderBytes = val
- }
- }
- func WithCert(certFile, keyFile string) OptionFunc {
- return func(opts *Options) {
- if certFile == "" || keyFile == "" {
- return
- }
- opts.CertFile = certFile
- opts.KeyFile = keyFile
- }
- }
|