commit 714f16a93e7fe78e8afa4a89b96ccb305806dc48 Author: 凌海仲子 Date: Fri Sep 3 23:15:39 2021 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66c9f95 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.exe +logs/ +.vscode/ +gin-standard +go.sum \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..29b255b --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +appname = gin-standard +serverip = 8.8.8.8 +serverport = 22 +apppath = /usr/local/gin + +.PHONY : linux +linux: + go mod tidy + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(appname) . + +.PHONY : windows +windows: + CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-s -w --extldflags "-static -fpic"' -o $(appname).exe . + +.PHONY : release +release: linux + ssh -p $(serverport) ubuntu@$(serverip) "sudo systemctl stop iap.service" + ssh -p $(serverport) ubuntu@$(serverip) "if [ ! -d $(apppath)/bak ]; then mkdir -p $(apppath)/bak; fi" + ssh -p $(serverport) ubuntu@$(serverip) "if [ -f $(apppath)/$(appname) ]; then cp $(apppath)/$(appname) $(apppath)/bak; fi" + ssh -p $(serverport) ubuntu@$(serverip) "if [ ! -d $(apppath)/docs ]; then mkdir -p $(apppath)/docs; fi" + scp -P $(serverport) ./docs/* ubuntu@$(serverip):$(apppath)/docs/ + scp -P $(serverport) ./$(appname) ubuntu@$(serverip):$(apppath) + ssh -p $(serverport) ubuntu@$(serverip) "sudo systemctl start iap.service" \ No newline at end of file diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..74dba18 --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,99 @@ +// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT +// This file was generated by swaggo/swag +package docs + +import ( + "bytes" + "encoding/json" + "strings" + "text/template" + + "github.com/swaggo/swag" +) + +var doc = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "termsOfService": "https://myschools.me/", + "contact": { + "name": "suguo.yao", + "url": "https://myschools.me/suguo/snippet", + "email": "ysg@myschools.me" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": {}, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + }, + "OAuth2Application": { + "type": "oauth2", + "flow": "application", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": " Grants read and write access to administrative information", + "write": " Grants write access" + } + } + } +}` + +type swaggerInfo struct { + Version string + Host string + BasePath string + Schemes []string + Title string + Description string +} + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = swaggerInfo{ + Version: "1.0", + Host: "s1.xintijiao.com", + BasePath: "/", + Schemes: []string{}, + Title: "浙大城院产业互联-GIN标准结构", + Description: "宁波团队提供技术支持", +} + +type s struct{} + +func (s *s) ReadDoc() string { + sInfo := SwaggerInfo + sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1) + + t, err := template.New("swagger_info").Funcs(template.FuncMap{ + "marshal": func(v interface{}) string { + a, _ := json.Marshal(v) + return string(a) + }, + "escape": func(v interface{}) string { + // escape tabs + str := strings.Replace(v.(string), "\t", "\\t", -1) + // replace " with \", and if that results in \\", replace that with \\\" + str = strings.Replace(str, "\"", "\\\"", -1) + return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1) + }, + }).Parse(doc) + if err != nil { + return doc + } + + var tpl bytes.Buffer + if err := t.Execute(&tpl, sInfo); err != nil { + return doc + } + + return tpl.String() +} + +func init() { + swag.Register(swag.Name, &s{}) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..9af3bd3 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,31 @@ +{ + "swagger": "2.0", + "info": { + "description": "宁波团队提供技术支持", + "title": "浙大城院产业互联-GIN标准结构", + "termsOfService": "https://myschools.me/", + "contact": { + "name": "suguo.yao", + "url": "https://myschools.me/suguo/snippet", + "email": "ysg@myschools.me" + }, + "version": "1.0" + }, + "host": "s1.xintijiao.com", + "basePath": "/", + "paths": {}, + "securityDefinitions": { + "BasicAuth": { + "type": "basic" + }, + "OAuth2Application": { + "type": "oauth2", + "flow": "application", + "tokenUrl": "https://example.com/oauth/token", + "scopes": { + "admin": " Grants read and write access to administrative information", + "write": " Grants write access" + } + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..78be4a6 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,23 @@ +basePath: / +host: s1.xintijiao.com +info: + contact: + email: ysg@myschools.me + name: suguo.yao + url: https://myschools.me/suguo/snippet + description: 宁波团队提供技术支持 + termsOfService: https://myschools.me/ + title: 浙大城院产业互联-GIN标准结构 + version: "1.0" +paths: {} +securityDefinitions: + BasicAuth: + type: basic + OAuth2Application: + flow: application + scopes: + admin: ' Grants read and write access to administrative information' + write: ' Grants write access' + tokenUrl: https://example.com/oauth/token + type: oauth2 +swagger: "2.0" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..15dc43f --- /dev/null +++ b/go.mod @@ -0,0 +1,56 @@ +module gin-standard + +go 1.17 + +require ( + github.com/gin-gonic/gin v1.7.4 + github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 + github.com/sirupsen/logrus v1.8.1 + github.com/spf13/viper v1.8.1 + github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 + github.com/swaggo/gin-swagger v1.3.1 + github.com/swaggo/swag v1.5.1 +) + +require ( + github.com/PuerkitoBio/purell v1.1.0 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-openapi/jsonpointer v0.17.0 // indirect + github.com/go-openapi/jsonreference v0.19.0 // indirect + github.com/go-openapi/spec v0.19.0 // indirect + github.com/go-openapi/swag v0.17.0 // indirect + github.com/go-playground/locales v0.13.0 // indirect + github.com/go-playground/universal-translator v0.17.0 // indirect + github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/json-iterator/go v1.1.11 // indirect + github.com/leodido/go-urn v1.2.0 // indirect + github.com/lestrrat-go/strftime v1.0.5 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/pelletier/go-toml v1.9.3 // indirect + github.com/pkg/errors v0.8.1 // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/ugorji/go/codec v1.1.13 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect + golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect + golang.org/x/text v0.3.6 // indirect + golang.org/x/tools v0.1.2 // indirect + google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/handler/ping-handler.go b/handler/ping-handler.go new file mode 100644 index 0000000..6e3ac6b --- /dev/null +++ b/handler/ping-handler.go @@ -0,0 +1,19 @@ +package handler + +import ( + "gin-standard/service" + "net/http" + + "github.com/gin-gonic/gin" +) + +func Ping(c *gin.Context) { + result, err := service.Ping() + if err != nil { + c.JSON(500, gin.H{ + "data": err.Error(), + }) + return + } + c.JSON(http.StatusOK, result) +} diff --git a/logger.go b/logger.go new file mode 100644 index 0000000..12ff626 --- /dev/null +++ b/logger.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + "time" + + rotatelogs "github.com/lestrrat-go/file-rotatelogs" + "github.com/rifflock/lfshook" + "github.com/sirupsen/logrus" +) + +func init() { + //日志初始化 + // logrus.SetOutput(os.Stdout) + logrus.SetOutput(ioutil.Discard) + logrus.SetFormatter(&logrus.TextFormatter{}) + logrus.SetLevel(logrus.DebugLevel) + logrus.AddHook(newLfsHook(7)) +} + +func newLfsHook(maxRemainCnt uint) logrus.Hook { + //检查与创建日志文件夹 + _, err := os.Stat("logs") + if os.IsNotExist(err) { + os.Mkdir("logs", 0755) + } + + logName := fmt.Sprintf(`logs/%s`, APPNAME) + writer, err := rotatelogs.New( + logName+"%Y%m%d.log", + rotatelogs.WithLinkName(logName), + rotatelogs.WithRotationTime(24*time.Hour), + rotatelogs.WithRotationCount(maxRemainCnt), + ) + + if err != nil { + panic("config local file system for logger error: " + err.Error()) + } + + lfsHook := lfshook.NewHook(lfshook.WriterMap{ + logrus.DebugLevel: writer, + logrus.InfoLevel: writer, + logrus.WarnLevel: writer, + logrus.ErrorLevel: writer, + logrus.FatalLevel: writer, + logrus.PanicLevel: writer, + }, &logrus.TextFormatter{}) + + return lfsHook +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..9a50d85 --- /dev/null +++ b/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "flag" + "net/http" + "time" + + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "github.com/spf13/viper" +) + +const ( + APPNAME = "snippet" +) + +// @title 浙大城院产业互联-GIN标准结构 +// @version 1.0 +// @description 宁波团队提供技术支持 +// @termsOfService https://myschools.me/ + +// @contact.name suguo.yao +// @contact.url https://myschools.me/suguo/snippet +// @contact.email ysg@myschools.me + +// @securityDefinitions.basic BasicAuth + +// @securitydefinitions.oauth2.application OAuth2Application +// @tokenUrl https://example.com/oauth/token +// @scope.write Grants write access +// @scope.admin Grants read and write access to administrative information + +// @host s1.xintijiao.com +// @BasePath / +func main() { + //配置读取 + cf := flag.String("config", "config.yaml", "file of config") + flag.Parse() + + viper.SetConfigFile(*cf) + if err := viper.ReadInConfig(); err != nil { + panic(err) + } + + //进行组件初始化 + + //api 服务启动 + router := gin.New() + setupRouter(router) + + s := &http.Server{ + Addr: viper.GetString("app.host"), + Handler: router, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + } + logrus.WithFields(logrus.Fields{ + "func": "main", + }).Infof("%s service on %s", APPNAME, viper.GetString("app.host")) + logrus.Fatal(s.ListenAndServe()) +} diff --git a/model/ping-model.go b/model/ping-model.go new file mode 100644 index 0000000..8b53790 --- /dev/null +++ b/model/ping-model.go @@ -0,0 +1 @@ +package model diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e69de29 diff --git a/router.go b/router.go new file mode 100644 index 0000000..8dc862e --- /dev/null +++ b/router.go @@ -0,0 +1,16 @@ +package main + +import ( + "gin-standard/handler" + + "github.com/gin-gonic/gin" + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" +) + +func setupRouter(router *gin.Engine) { + router.Use(gin.Recovery()) + url := ginSwagger.URL("http://localhost:8080/swagger/doc.json") + router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) + router.GET(`/ping`, handler.Ping) +} diff --git a/service/ping-service.go b/service/ping-service.go new file mode 100644 index 0000000..1d95b20 --- /dev/null +++ b/service/ping-service.go @@ -0,0 +1,5 @@ +package service + +func Ping() (interface{}, error) { + return "hello world.", nil +} diff --git a/standardhttp b/standardhttp new file mode 100644 index 0000000..9f9fef9 --- /dev/null +++ b/standardhttp @@ -0,0 +1,11 @@ +@url=http://localhost:8080 +@token=eyJhbGciOiJIUzI1NiIsInR5 + + +#### ping +GET {{url}}/ping HTTP/1.1 + + + + +