Categorygithub.com/shrewx/ginx
modulepackage
1.1.4
Repository: https://github.com/shrewx/ginx.git
Documentation: pkg.go.dev

# README

使用文档

介绍

接口结构参考httptransport设计思想,对gin做了封装,并使用httptransport的openapi和client自动生成工具适配。 封装目的主要有几点:

  1. 规范接口定义,解析传入参数的统一处理
  2. 使用注释+代码自动生成openapi和client端,更加方便快捷。

快速上手

example

说明

路由

所有的路由定义需要实现HandleOperator这个接口,里面包括三个方法

  • Path() string // 说明该路由的路径
  • Method() string // 说明该路由的HTTP Method
  • Output(ctx *gin.Context) (interface{}, error) // 接口的具体功能逻辑

例如:

type GetHelloWorld struct {
    ginx.MethodGet
}

type GetHelloWorldResponse struct {
    Message string `json:"message"`
}

func (g *GetHelloWorld) Path() string {
    return "/hello"
}

func (g *GetHelloWorld) Output(ctx *gin.Context) (interface{}, error) {
    return GetHelloWorldResponse{Message: "hello world"}, nil
}

这就是一个接口的完整定义,并且建议一个接口一个文件,文件名可与类名相同,如get_hello_world.go,这样开发者方便查看和修改。

其中Output(ctx *gin.Context) (interface{}, error) 有两个返回值。

第一个定义为interface,即返回任何类型的对象都可以, 框架会判断其类型来设置不同的ContextType(默认使用application/json)

第二个是error,为了规范错误码的定义,使用statuserror库和自动化工具进行生成,错误码返回结构定义为:

{
  "key": "DDIResourceNotFound", 
  "code": "404000000001", 
  "message": "视图未找到",
}

如果返回的error没有实现CommonError这个接口,错误就会封装成status_error.CommonError

status_error.CommonError{
    Key:     "InternalServerError",
    Code:    http.StatusBadGateway,
    Message: e.Error(),
}

和gin对比


ir.GET("/hello", func (context *gin.Context) {
    context.JSON(http.StatusOK, struct {
        Message string `json:"message"`
        }{
	 Message: "hello world"
	})
    }
)

路由组

路由组定义一组路由的相同的路径前缀,和gin的Group是一个概念。

例如:

var (
	V0Router = ginx.NewRouter(ginx.Group("v0"))
)

func init() {
	V0Router.Register(&GetHelloWorld{})
}

那么GetHelloWorld这个接口的完整路径就是/v0/hello

和gin对比

group := ir.Group("v0")
group.GET("/hello", func (context *gin.Context) {
context.JSON(http.StatusOK, struct {
Message string `json:"message"`
    }{
	Message: "hello world"
    })
  }
)

中间件

中间件需要实现的接口是TypeOperator,里面包括两个方法:

  • Output(ctx *gin.Context) (interface{}, error)
  • Type() string

若需要实现一个认证功能,所有接口都必须进行用户密码认证后才能访问则代码实现如下:

type BaseAuth struct {
	ginx.MiddlewareType
}

func (g *BaseAuth) Output(ctx *gin.Context) (interface{}, error) {
	return gin.BasicAuth(map[string]string{
		"admin": "admin",
	}), nil
}

var V0Router = ginx.NewRouter(ginx.Group("v0"), &BaseAuth{})

和gin对比

group := ir.Group("v0",gin.BasicAuth(map[string]string{
    "admin": "admin",
}))

请求参数

请求参数类型通过tag进行区分,使用关键字in声明参数类型,name声明参数名称,框架会自动解析请求的参数,并填充到结构体对应的成员变量中方便实用

同时使用了validator库,对参数进行校验, 使用关键字validate声明校验规则

参数类型如下:

Query、Path

type GetUserInfo struct {
	ginx.MethodGet
	Username string `in:"query" validate:"required"`
	ID       int    `in:"path" validate:"min=10"`
}

func (g *GetUserInfo) Path() string {
	return "/:id"
}

func (g *GetUserInfo) Output(ctx *gin.Context) (interface{}, error) {
	logfile.Info("id: ", g.ID, " username: ", g.Username)
	return nil, nil
}

Header

type BaseAuth struct {
	ginx.HTTPBasicAuthSecurityType
	Name string `in:"header" name:"Authorization"`
}

func (g *BaseAuth) Output(ctx *gin.Context) (interface{}, error) {
	if g.Name != authorization("admin", "admin") {
		return nil, errors.Unauthorized
	}

	return nil, nil
}

Form-data

type PutUserInfo struct {
	ginx.MethodPost
	Name    string `in:"form" name:"name"`
	Age     int    `in:"form" name:"age"`
	Address string `in:"form" name:"address"`
}

Form-Multipart

type UploadFile struct {
	ginx.MethodPost
	File *multipart.FileHeader `in:"multipart" name:"file1"`
}

func (u *UploadFile) Output(ctx *gin.Context) (interface{}, error) {
	if u.File == nil {
		return nil, errors.UploadFileIsNotExist
	}

	if err := ctx.SaveUploadedFile(u.File, u.File.Filename); err != nil {
		return nil, err
	}

	return nil, nil
}

Form-urlencoded

type ModifyUserInfo struct {
	ginx.MethodPut
	Name string `in:"urlencoded" name:"name"`
}

Body

body类型里面tag直接使用json就可

type CreateUserInfo struct {
	ginx.MethodPost
	Body struct {
		Name    string `json:"name"`
		Age     int    `json:"age"`
		Address string `json:"address"`
	} `in:"body"`
}

其他

如果以上都不满足要求,可直接使用gin的库的对应的方法获取请求参数。

ContentType

如上面提到的,默认的情况下response的contentType是application/json, 如果需要其他类型的,框架封装了一些Mine结构体可使用。

文件下载

func (g *DownloadFile) Output(ctx *gin.Context) (interface{}, error) {
	file := ginx.NewAttachment("text.txt", ginx.MineApplicationOctetStream)
	file.Write([]byte("hello world"))
	return file, nil
}

HTML

func (g *HTML) Output(ctx *gin.Context) (interface{}, error) {
	html := ginx.NewHTML()
	html.Write([]byte("<body> hello world</body>"))
	return html, nil
}

Image

func (g *Image) Output(ctx *gin.Context) (interface{}, error) {
	png := ginx.NewImagePNG()
	file, err := os.ReadFile("./router/file/go.png")
	if err != nil {
		return nil, err
	}
	png.Write(file)
	return png, nil
}

其他

如果框架中列出的Mine都不满足,可以自行实现MineDescriber接口或者直接使用gin的ctx.Data方法设置

func (g *OtherType) Output(ctx *gin.Context) (interface{}, error) {
	ctx.Data(http.StatusOK, "other_type", []byte("hello world"))
	return nil, nil
}

注释Swagger

生成swagger文档go常见方式是使用go-swagger库搭配注释的形式,该库同样也是通过注释的形式来实现swagger文档的生成。 有所不同的是不需要特定的tag说明,而是使用ast库对代码进行所有注释的扫描,并且对响应结果和错误都会进行类型判断。

func init() {
	Router.Register(&CreateUserInfo{})
}

// 创建用户信息
type CreateUserInfo struct {
	ginx.MethodPost
	ID int   `in:"path"`
	Body struct {
		// 名称
		Name    string ` json:"name"`
		// 年龄
		Age     int    `json:"age"`
		// 地址
		Address string `json:"address"`
	} `in:"body"`
}

type CreateUserInfoResponse struct{
	
}

func (g *CreateUserInfo) Path() string {
	return "/:id"
}

func (g *CreateUserInfo) Output(ctx *gin.Context) (interface{}, error) {
	logfile.Info(g.Body.Name, g.Body.Age, g.Body.Address)
	return nil, nil
}

由于go-swagger暂时只支持到openapi2.0, 而本库使用的是openapi3.0,所以就没有直接通过引入go-swagger库来展示swagger ui,而是通过docker启动了swaggerui达到相同效果。使用到的命令是:

go install github.com/shrewx/toolx

toolx swagger -p "swagger ui 页面的端口,默认9200" -s "后台提供服务的地址,默认http://127.0.0.1:8888"

容器启动以后,就可以访问对应的页面

2022-07-31-16-38-36.png

如果只需要生成openapi则使用命令:

toolx gen openapi -p "后台服务代码路径,默认为当前路径"

Client生成

为了方便其他服务调用,可自动生成client相关代码,命令为:

toolx gen client -s "客户端名称" -u "openapi.jso(支持url和本地路径)"

提高开发效率

Goland添加接口模版

在 Preferences --> Editor --> Live Template 添加一个Go Template

import (
	"github.com/shrewx/ginx"
	"github.com/gin-gonic/gin"
)

func init() {
	Router.Register(&$Struct${})
}

type $Struct$ struct {
	ginx.MethodGet
}

func (g *$Struct$) Path() string {
	return ""
}

func (g *$Struct$) Output(ctx *gin.Context) (interface{}, error) {
	$END$
	return nil, nil
}

# Packages

No description provided by the author

# Functions

AddCommand function is add command to cli.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Launch function is program entry, you can start a server like this: ginx.Launch(func(cmd *cobra.Command, args []string) { ginx.Parse(&ServerConfig) ginx.RunServer(ServerConfig, router.V0Router) }).
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Parse function is parse the config file support yaml, json, toml, env.
No description provided by the author
No description provided by the author
No description provided by the author
SetI18n function is set the language of message Default I18n is ZH, this will set to cookie.

# Constants

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Interfaces

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Type aliases

No description provided by the author