github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/gin_app/gin.go (about)

     1  package gin_app
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"os"
     8  	"os/signal"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/gin-contrib/cors"
    13  	"github.com/gin-gonic/gin"
    14  
    15  	"github.com/artisanhe/tools/conf"
    16  	"github.com/artisanhe/tools/env"
    17  )
    18  
    19  type GinApp struct {
    20  	Name        string
    21  	IP          string
    22  	Port        int
    23  	SwaggerPath string
    24  	WithCORS    bool
    25  	app         *gin.Engine
    26  }
    27  
    28  func (a GinApp) DockerDefaults() conf.DockerDefaults {
    29  	return conf.DockerDefaults{
    30  		"Port":     80,
    31  		"WithCORS": false,
    32  	}
    33  }
    34  
    35  func (a GinApp) MarshalDefaults(v interface{}) {
    36  	if g, ok := v.(*GinApp); ok {
    37  		if g.Name == "" {
    38  			g.Name = os.Getenv("PROJECT_NAME")
    39  		}
    40  
    41  		if g.SwaggerPath == "" {
    42  			g.SwaggerPath = "./swagger.json"
    43  		}
    44  
    45  		if g.Port == 0 {
    46  			g.Port = 80
    47  		}
    48  	}
    49  }
    50  
    51  func (a *GinApp) Init() {
    52  	if env.IsOnline() {
    53  		gin.SetMode(gin.ReleaseMode)
    54  	}
    55  
    56  	a.app = gin.New()
    57  
    58  	if a.WithCORS {
    59  		a.app.Use(cors.New(cors.Config{
    60  			AllowAllOrigins:  true,
    61  			AllowMethods:     []string{"GET", "POST", "PUT", "HEAD", "DELETE", "PATCH"},
    62  			AllowHeaders:     []string{"Origin", "Content-Length", "Content-Type", "Authorization", "AppToken", "AccessKey", "Cookie"},
    63  			AllowCredentials: true,
    64  			MaxAge:           12 * time.Hour,
    65  		}))
    66  	}
    67  
    68  	a.app.Use(gin.Recovery(), WithServiceName(a.Name), Logger())
    69  }
    70  
    71  type GinEngineFunc func(router *gin.Engine)
    72  
    73  func (a *GinApp) Register(ginEngineFunc GinEngineFunc) {
    74  	ginEngineFunc(a.app)
    75  }
    76  
    77  func (a *GinApp) Start() {
    78  	a.MarshalDefaults(a)
    79  	a.app.GET("/healthz", func(c *gin.Context) {})
    80  
    81  	srv := &http.Server{
    82  		Addr:    a.getAddr(),
    83  		Handler: a.app,
    84  	}
    85  
    86  	go func() {
    87  		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
    88  			fmt.Fprintf(os.Stderr, "Server run failed[%s]\n", err.Error())
    89  			os.Exit(1)
    90  		}
    91  	}()
    92  
    93  	quit := make(chan os.Signal, 1)
    94  	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    95  	<-quit
    96  
    97  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    98  	defer cancel()
    99  
   100  	if err := srv.Shutdown(ctx); err != nil {
   101  		fmt.Printf("Server Shutdown on failed[%+v]\n", err)
   102  	}
   103  
   104  	time.Sleep(2 * time.Second)
   105  	fmt.Printf("Server exiting\n")
   106  }
   107  
   108  func (a GinApp) getAddr() string {
   109  	return fmt.Sprintf("%s:%d", a.IP, a.Port)
   110  }