gors

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2023 License: MIT Imports: 4 Imported by: 0

README

gors

gors是一个代码生产器,基于个服务接口和描述,自动创建一个符合gin路由规则的服务.

快速开始

  1. 安装gors:
go install github.com/go-leo/gors/cmd/gors@latest
  1. 定义一个服务接口:
//go:generate gors -service Service

// Service
// @GORS @Path("/api)  @Path("/v1)
type Service interface {
	// Method
    // @GORS @GET @Path("/method/:id) @UriBinding @JSONRender
    Method(context.Context, *MethodReq) (*MethodResp, error)
}
type MethodReq struct {
	ID int `uri:"id"`
}
type MethodResp struct {
	V int `json:"v,omitempty"`
}
  1. 运行一下命令,生产文件service_gors.go
go generate ./...
// Code generated by "gors -service Service"; DO NOT EDIT.
package demo

import (
	gin "github.com/gin-gonic/gin"
	gors "github.com/go-leo/gors"
	http "net/http"
)

func ServiceRoutes(srv Service) []gors.Route {
	return []gors.Route{
		{
			HTTPMethod: http.MethodGet,
			Path:       "/api/v1/method/:id",
			HandlerFunc: func(c *gin.Context) {
				var req *MethodReq
				var resp *MethodResp
				var err error
				req = new(MethodReq)
				if err = c.BindUri(req); err != nil {
					c.String(http.StatusBadRequest, err.Error())
					_ = c.Error(err).SetType(gin.ErrorTypeBind)
					return
				}
				if err := gors.Validate(req); err != nil {
					c.String(http.StatusBadRequest, err.Error())
					_ = c.Error(err).SetType(gin.ErrorTypeBind)
					return
				}
				ctx := gors.NewContext(c)
				resp, err = srv.Method(ctx, req)
				if err != nil {
					if httpErr, ok := err.(*gors.HttpError); ok {
						c.String(httpErr.StatusCode(), httpErr.Error())
						_ = c.Error(err).SetType(gin.ErrorTypePublic)
						return
					}
					c.String(http.StatusInternalServerError, err.Error())
					_ = c.Error(err).SetType(gin.ErrorTypePrivate)
					return
				}
				statusCode := gors.GetCodeFromContext(ctx)
				c.JSON(statusCode, resp)
			},
		},
	}
}
  1. 实现服务接口
var _ demo.Service = new(Service)

type Service struct {}

func (svc *Service) Method(ctx context.Context, req *demo.MethodReq) (*demo.MethodResp, error) {
	fmt.Println(req.ID)
	return &demo.MethodResp{V: 10}, nil
}
  1. 创建gin.Engine,注册路由并启动http服务:
var routers []gors.Router
routers = append(routers, demo.ServiceRouters(new(svc.Service))...)

engine := gin.New()
for _, router := range routers {
    engine.Handle(router.HTTPMethod, router.Path, router.HandlerFunc)
}

srv := http.Server{Handler: engine}
listen, err := net.Listen("tcp", ":8088")
if err != nil {
    panic(err)
}
err = srv.Serve(listen)
if err != nil {
    panic(err)
}

方法入参

参数一

第一个参数必须是context.Context,其他类型都会生成失败。

参数二

第二个参数有四种类型:io.Reader[]bytestring结构体指针,其他类型都会生成失败。

  • io.Reader,直接取http.Request里的Body。所有Binding策略都不能用。
  • []byte,将http.Request里的Body以字节数组形式全部读出。所有Binding策略都不能用。
  • string,将http.Request里的Body以字符串形式全部读出。所有Binding策略都不能用。
  • 结构体指针,所有Binding策略都适用,将path、query、header和body中的参数,绑定到内部字段里。

响应

参数一

第一个响应参数有四种类型:string[]byteio.Reader结构体指针,其他类型都会生成失败。

  • io.Reader,将io.Reader写入响应的Body中,必须要配合@ReaderRender注解使用,可以自定义响应Content-Type,比如@ReaderRender(video/mpeg4)
  • []byte,将[]byte写入响应的Body中,必须要配合@BytesRender注解使用,可以自定义响应Content-Type,比如@BytesRender(image/png)
  • string,可以配合不同的Render策略进行响应。
    • @TextRender, 将文本以Content-Type"text/plain; charset=utf-8"写入响应的Body中。
    • @HTMLRender, 将文本以Content-Type"text/html; charset=utf-8"写入响应的Body中。
    • @StringRender, 将文本写入响应的Body中,可以自定义响应Content-Type,比如@StringRender(text/xml)
    • @RedirectRender, 重定向渲染,重定向到文本指定的位置。
  • 结构体指针,需要配合各自Render策略,将结构体指针序列化成[]byte后,写入响应的Body中。

参数二

第一个请求参数必须是error,其他类型都会生成失败。 如果error是*gors.HttpError类型,将设置指定的status code,然后将错误的文本写入响应的Body。 否则会设置500的status code,然后将错误的文本写入响应的Body。

注解大全

@GORS

必须设置, 基础注解。 代表gors的注解配置的开始,没有@GORS开始的都会被忽略。

@Path

必须设置,路径注解。

  • 可以设置参数,@Path(/api)
  • 如果设置在接口名上,代表为所有path定义基础的path。
  • 如果设置在方法上,代表为此方法定义path。
  • 可以设置多个@Path注解,此时多个path会被拼接成一个。

HTTP Method注解

必须设置,设置此方法的只能响应指定的Method请求。 Method只能有一个有效,如果设置多个,只有最后一个有效。支持标准库里定义的9种method:

@GET

此注解设置此方法为Get请求。

@HEAD

此注解设置此方法为Head请求。

@POST

此注解设置此方法为Post请求。

@PUT

此注解设置此方法为Put请求。

@PATCH

此注解设置此方法为Patch请求。

@DELETE

此注解设置此方法为Delete请求。

@CONNECT

此注解设置此方法为Connect请求。

@OPTIONS

此注解设置此方法为Options请求。

@TRACE

此注解设置此方法为Trace请求。

Binding 注解

数据绑定注解。

  • 当第二个参数是结构体指针时候,可以设置。
  • 可以设置多种Binding策略。
@UriBinding

将对应的Uri参数绑定到结构体指针中。

支持gin的路径参数语法gin的uri绑定策略

@QueryBinding

将对应的Query参数绑定到结构体指针中。

支持gin的只绑定Query策略

@HeaderBinding

将对应的Header参数绑定到结构体指针中。

支持gin的header绑定策略

@JSONBinding

将请求的Body以JSON形式解析出来,并绑定到结构体指针中。

@XMLBinding

将请求的Body以XML形式解析出来,并绑定到结构体指针中。

@FormBinding

将请求的Query和Body同时以Form形式解析出来,并绑定到结构体指针中。

不支持文件上传。

支持gin的form绑定策略

@FormPostBinding

将请求的Body以FormPost形式解析出来,并绑定到结构体指针中。

只支持application/x-www-form-urlencoded的Form请求。

不支持文件上传。

支持gin的urlencoded绑定策略

@FormMultipartBinding

将请求的Body以Multipart形式解析出来并绑定到结构体指针中。

只支持multipart/form-data的Form请求。

支持文件上传。

支持gin的Multipart绑定策略

@ProtoBufBinding

将请求的Body以protobuf形式解析出来并绑定到结构体指针中。

@MsgPackBinding

将请求的Body以msgpack形式解析出来并绑定到结构体指针中。

@YAMLBinding

将请求的Body以YAML形式解析出来并绑定到结构体指针中。

@TOMLBinding

将请求的Body以TOML形式解析出来并绑定到结构体指针中。

Render 注解

响应渲染注解。

  • 方法的一个返回参数的类型不通,相对应的渲染也不同。
  • 只能设置一种渲染策略。
@BytesRender

字节数组渲染。

只有当方法的第一个返回参数类型为[]byte时才能使用,@BytesRender将数据以字节数组写入响应的Body中,可以自定义响应Content-Type,比如:@BytesRender(image/png)代表渲染一张图片。

@StringRender

字符串渲染。

只有当方法的第一个返回参数类型为string时才能使用,@StringRender将数据以文本的方式写入响应的Body中,可以自定义响应Content-Type,比如@StringRender(image/xml)代表渲染xml文件。

@TextRender

文本渲染。

只有当方法的第一个返回参数类型为string时才能使用,@TextRender将数据以文本的方式写入响应的Body中,Content-Type固定为text/plain; charset=utf-8

@HTMLRender

HTML渲染。

只有当方法的第一个返回参数类型为string时才能使用,@HTMLRender将数据以文本的方式写入响应的Body中,Content-Type固定为text/html; charset=utf-8

@RedirectRender

重定向渲染。

只有当方法的第一个返回参数类型为string时才能使用,此参数应该是个可以重定向的地址位置。

@ReaderRender

数据流渲染,只有当方法的第一个返回参数类型为io.Reader时才能使用,@ReaderRender将数据流写入响应的Body中,可以自定义响应Content-Type,比如:@ReaderRender(video/mpeg4)代表渲染一个视频文件。

@JSONRender

JSON渲染。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@JSONRender将结构体指针以JSON格式序列化并且写入响应的Body中,Content-Type固定为application/json; charset=utf-8。参考gin文档-json

@IndentedJSONRender

漂亮的JSON渲染,在JSON渲染的基础上,加上了缩进和结束行。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@IndentedJSONRender将结构体指针以JSON格式序列化并且写入响应的Body中,Content-Type固定为application/json; charset=utf-8。比较耗资源。

@SecureJSONRender

安全的的JSON渲染,防止一些代码注入。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@SecureJSONRender将结构体指针以JSON格式序列化并且写入响应的Body中,Content-Type固定为application/json; charset=utf-8gin文档-SecureJSON

@JsonpJSONRender

jsonp方式渲染,jsonp可以跨域请求,如果查询参数callback存在,则将callback添加到响应体中。

只有当方法的第一个返回参数类型为结构体指针时才能使用。参考gin文档-jsonp

@PureJSONRender

纯净的JSON渲染,普通的JSON渲染,会将一些html特殊字符会被转义,比如<转成\u003c@PureJSONRender则不会转义。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@PureJSONRender将结构体指针以JSON格式序列化并且写入响应的Body中,Content-Type固定为application/json; charset=utf-8gin文档-PureJSON

@AsciiJSONRender

AsciiJSON渲染,只渲染Ascii字符,非Ascii字符则会被转义。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@AsciiJSONRender将结构体指针以JSON格式序列化并且写入响应的Body中,Content-Type固定为application/json; charset=utf-8gin文档-AsciiJSON

@XMLRender

XML渲染。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@XMLRender将结构体指针以XML格式序列化并且写入响应的Body中,Content-Type固定为application/xml; charset=utf-8。参考gin文档-XMLRender

@YAMLRender

YAML渲染。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@YAMLRender将结构体指针以YAML格式序列化并且写入响应的Body中,Content-Type固定为application/x-yaml; charset=utf-8。参考gin文档-YAMLRender

@ProtoBufRender

ProtoBuf渲染。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@ProtoBufRender将结构体指针以Protocol Buffer格式序列化并且写入响应的Body中,Content-Type固定为application/x-protobuf。参考gin文档-ProtoBufRender

@MsgPackRender

MsgPack渲染。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@MsgPackRender将结构体指针以MsgPack格式序列化并且写入响应的Body中,Content-Type固定为application/msgpack; charset=utf-8

@TOMLRender

TOML渲染。

只有当方法的第一个返回参数类型为结构体指针时才能使用,@TOMLRender将结构体指针以TOML格式序列化并且写入响应的Body中,Content-Type固定为application/toml。参考gin文档-TOMLRender

Validate

除了gin框架支持的参数校验方案外,gors也提供了另外一种参数校验方式,方法的第一个返回参数类型为结构体指针,并且实现了Validator接口,则在数据绑定后,会对数据进行校验。

Validator接口

type Validator interface {
	Validate() error
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendRichRoutes added in v1.1.1

func AppendRichRoutes[R gin.IRoutes](iRoutes R, routes []RichRoute) R

func AppendRoutes added in v1.1.1

func AppendRoutes[R gin.IRoutes](iRoutes R, routes []Route) R

func FromContext

func FromContext(ctx context.Context) *gin.Context

FromContext 从context获取gin.Contenxt

func GetCodeFromContext

func GetCodeFromContext(ctx context.Context) int

GetCodeFromContext 从context获取status code

func InterruptHandle added in v1.1.1

func InterruptHandle(ctx context.Context)

InterruptHandle 向context设置中断处理

func IsInterrupted added in v1.1.1

func IsInterrupted(ctx context.Context) bool

IsInterrupted 从context获取是否中断处理

func NewContext

func NewContext(c *gin.Context) context.Context

NewContext 向context注入gin.Contenxt

func SetCodeToContext

func SetCodeToContext(ctx context.Context, code int)

SetCodeToContext 向context设置status code

func Validate

func Validate(req interface{}) error

Types

type HttpError

type HttpError struct {
	// contains filtered or unexported fields
}

func NewHttpError

func NewHttpError(statusCode int, err error) *HttpError

func (HttpError) Error

func (h HttpError) Error() string

func (HttpError) StatusCode

func (h HttpError) StatusCode() int

type RichRoute added in v1.1.1

type RichRoute interface {
	Method() string
	Path() string
	Handlers() []gin.HandlerFunc
}

func NewRichRoute added in v1.1.1

func NewRichRoute(route Route, middlewares ...gin.HandlerFunc) RichRoute

type Route

type Route interface {
	Method() string
	Path() string
	Handler() gin.HandlerFunc
}

func NewRoute

func NewRoute(method string, path string, handler gin.HandlerFunc) Route

type Validator

type Validator interface {
	Validate() error
}

Directories

Path Synopsis
cmd
example
cmd
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL