pick

package module
v1.5.25 Latest Latest
Warning

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

Go to latest
Published: Jul 19, 2024 License: BSD-3-Clause Imports: 26 Imported by: 3

README

pick框架

一个基于反射的自动注入api开发框架http api服务器,灵感来自于grpc和springmvc,pick的路由基于httprouter改造,如不想使用,pick同时兼容gin,fiber(fasthttp),底层可选择。

特点

  • 摆脱路由注册

    摆脱零散的各处的路由注册 xxx.Handle("/",func(){})

  • 摆脱w,r,摆脱xxx.Context

    不再编写这样func(w http.ResponseWriter, r *http.Request)或者func(ctx xxx.Context){ctx.XXX()}的业务代码

  • 专注于业务
func (*UserService) Add(ctx *httpctx.Context, req *model.SignupReq) (*model.User, error) {
	//对于一个性能强迫症来说,我宁愿它不优雅一些也不能接受每次都调用
	pick.Api(func() {
		return pick.Post("").//定义请求的方法及路由
			Title("用户注册").//接口描述
            Middleware(nil).//中间件
            //接口迭代信息
			CreateLog("1.0.0", "jyb", "2019/12/16", "创建").//创建,唯一
			ChangeLog("1.0.1", "jyb", "2019/12/16", "修改测试").//变更,可有多个
			Deprecated("1.0.0", "jyb", "2019/12/16", "删除").//废弃,唯一
            End()
	})

	return &model.User{Name: "测试"}, nil
}

使用

go get github.com/hopeio/pick

快速开始

首先我们需要定义一个服务

type UserService struct{}
//需要实现Service方法,返回该服务的说明,url前缀,以及需要的中间件
func (*UserService) Service() (string, string, []http.HandlerFunc) {
    return "用户相关", "/api/v1/user", []http.HandlerFunc{middleware.Log}
}

然后可以写我们的业务方法


func (*UserService) AddV2(ctx *httpctx.Context, req *model.SignupReq) (*model.User, error) {
	//对于一个性能强迫症来说,我宁愿它不优雅一些也不能接受每次都调用
	pick.Api(func() {
		return pick.Post("").
			Title("用户注册").
			CreateLog("1.0.0", "jyb", "2019/12/16", "创建").
			ChangeLog("1.0.1", "jyb", "2019/12/16", "修改测试").
            End()
	})

	return &model.User{Name: "测试"}, nil
}


func (*UserService) Edit(ctx *httpctx.Context, req *model.User) (*model.User, error) {
	pick.Api(func() {
		return pick.Put("/:id").
			Title("用户编辑").
			CreateLog("1.0.0", "jyb", "2019/12/16", "创建").
			Deprecated("1.0.0", "jyb", "2019/12/16", "删除").
            End()
	})

	return nil, nil
}

这会生成如下的Api

 API:	 POST   /api/v1 /user   用户注册
 API:	 PUT    /api/v1/user/:id   用户编辑(废弃)

第一个参数可以用于身份验证,当然你必须自己实现 作为一个例子,jwt验证,这会直接在传入我们的业务方法前调用

import (
  "errors"
  "github.com/golang-jwt/jwt/v5"
  "github.com/hopeio/context/httpctx"
)

type AuthInfo struct {
  Id int
  jwt.RegisteredClaims
}

func ParseAuthInfo(ctx *httpctx.Context) (*AuthInfo, error) {
  token := ctx.Request.Header.Get("Authorization")
  authInfo := &AuthInfo{}
  if token == "" {
    return nil, errors.New("未登录")
  }
  tokenClaims, _ := (&jwt.Parser{}).ParseWithClaims(token, authInfo, func(token *jwt.Token) (interface{}, error) {
    return "TokenSecret", nil
  })
  
  if tokenClaims != nil {
    if claims, ok := tokenClaims.Claims.(*AuthInfo); ok && tokenClaims.Valid {
    return claims,nil
    }
  }
  return nil,errors.New("未登录")
}

第二个参数为我们定义的参数, 返回值分别是自定义的返回结构体及错误,

作为一个建议这部分可以用protobuf定义,简直完美,当然这样得为第一个参数实现Context

如果是复杂场景呢,我们也是可以注册http.HandlerFunc的

router.Handle(http.MethodGet, "/api-doc/md", "api文档", func(w http.ResponseWriter, req *http.Request) {
			w.Write([]byte(doc))
			w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		})

然后,注册我们的服务

func init(){
    pickrouter.RegisterService(&service.UserService{})
}

当然你可以注册多个

func init(){
    pickrouter.RegisterService(&service.UserService{},&other.Service{})
}

最后启动我们的服务

func main() {
    //是否生成文档
	router := pickrouter.NewRouter(true)
    pickrouter.ServeFiles("/static", "E:/")
	log.Println("visit http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", router))
}

它是如此的简单

文档生成

是的,你看到了pick.NewRouter(true),当传入true时,会为我们生成文档 当然,这需要你定义的请求配合,例如

type User struct {
	Id uint64 `json:"id"`
	Name string `json:"name" comment:"名字" validate:"gte=3,lte=10"`
	Password string `json:"password" comment:"密码" validate:"gte=8,lte=15"`
	Mail string `json:"mail" comment:"邮箱" validate:"email"`
	Phone string `json:"phone" comment:"手机" validate:"phone"`
}

如果你需要markdown文档,/api-doc/markdown 它会为我们生成如下文档

[TOC]

用户相关


用户注册-v1(/api/v1/user)

POST /api/v1/user (Principal jyb)

接口记录

版本 操作 时间 负责人 日志
1.0.0 创建 2019/12/16 jyb 创建
1.0.1 变更 2019/12/16 jyb 修改测试

参数信息

字段名称 字段类型 字段描述 校验要求
name string 名字 长度必须至少为3个字符
password string 密码 长度必须至少为8个字符
mail string 邮箱 必须是一个有效的手机号!
请求示例
{
	"name": "耰塧囎飿段",
	"password": "虱鷅磷黽楑",
	"mail": "盬艦潦昊譙"
}  

返回信息

字段名称 字段类型 字段描述
id number
name string 名字
password string 密码
mail string 邮箱
mail string 手机
返回示例
{
	"id": 1357,
	"name": "鐷嚅凮珘緻",
	"password": "梊朖迍髽栳"
}  

用户编辑-v1(废弃)(/api/v1/user/:id)

PUT /api/v1/user/:id (Principal jyb)

接口记录

...

是的,示例并不那么好看,并非不能支持简体字和英文字母,我计划单独写一个mock模块

当然你钟情swagger,也可以/api-doc/swagger Image text

Documentation

Index

Constants

View Source
const Template = `` /* 349-byte string literal not displayed */

Variables

View Source
var (
	ErrorType = reflect.TypeOf((*error)(nil)).Elem()
)
View Source
var (
	HttpContextType = reflect.TypeOf((*httpctx.Context)(nil))
)

Functions

func Api

func Api(f func())

func CommonHandler added in v1.5.25

func CommonHandler(w http.ResponseWriter, req *http.Request, handle *reflect.Value, ps *Params)

func Connect

func Connect(p string) *apiInfo

func DefinitionsApi

func DefinitionsApi(definitions map[string]spec.Schema, v interface{}, exclude []string)

func Delete

func Delete(p string) *apiInfo

func DocList added in v1.5.0

func DocList(w http.ResponseWriter, r *http.Request)

func Get

func Get(p string) *apiInfo

func GetMethodInfo

func GetMethodInfo(method *reflect.Method, preUrl string, httpContext reflect.Type) (info *apiInfo)

recover捕捉panic info

func Head(p string) *apiInfo

func Log

func Log(method, path, title string)

func Markdown

func Markdown(filePath, modName string)

有swagger,有没有必要做

func Options

func Options(p string) *apiInfo

func Patch

func Patch(p string) *apiInfo

func Post

func Post(p string) *apiInfo

func Put

func Put(p string) *apiInfo

func RegisterApiInfo added in v1.5.0

func RegisterApiInfo(apiInfo *GroupApiInfo)

func Registered

func Registered()

func ResWriteReflect added in v1.5.6

func ResWriteReflect(w http.ResponseWriter, traceId string, result []reflect.Value)

func Swagger

func Swagger(filePath, modName string)

func Trace

func Trace(p string) *apiInfo

Types

type ApiDocInfo

type ApiDocInfo struct {
	ApiInfo *apiInfo
	Method  reflect.Type
}

type ApiInfo

type ApiInfo struct {
	Path, Method, Title string
	Version             int
	Changelog           []changelog
	Createlog           changelog
	Deprecated          *changelog
	Middleware          []http.HandlerFunc
}

func (*ApiInfo) GetApiInfo

func (api *ApiInfo) GetApiInfo() *apiInfo

type GroupApiInfo

type GroupApiInfo struct {
	Describe string
	Infos    []*ApiDocInfo
}

type PMApi

type PMApi struct {
	Name                    string                    `json:"name"`
	ProtocolProfileBehavior PMProtocolProfileBehavior `json:"protocolProfileBehavior"`
	Request                 PMRequest                 `json:"request"`
	Response                []interface{}             `json:"response"`
}

type PMBody

type PMBody struct {
	Mode string `json:"mode"`
	Raw  string `json:"raw"`
}

type PMCategory

type PMCategory struct {
	Name                    string                    `json:"name"`
	ProtocolProfileBehavior PMProtocolProfileBehavior `json:"protocolProfileBehavior"`
	Items                   []PMApi                   `json:"item"`
}

type PMFile

type PMFile struct {
	Info  PMInfo       `json:"info"`
	Items []PMCategory `json:"item"`
}

type PMHeader

type PMHeader struct {
	Key     string `json:"key"`
	Value   string `json:"value"`
	Type    string `json:"type"`
	Disable bool   `json:"disable"`
}

TODO

type PMInfo

type PMInfo struct {
	PostManId string `json:"_postman_id"`
	Name      string `json:"name"`
	Schema    string `json:"schema"`
}

type PMProtocolProfileBehavior

type PMProtocolProfileBehavior struct {
	DisableBodyPruning bool `json:"disableBodyPruning"`
}

type PMQuery

type PMQuery struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type PMRequest

type PMRequest struct {
	Method      string     `json:"method"`
	Header      []PMHeader `json:"header"`
	Body        PMBody     `json:"body"`
	Description string     `json:"description"`
	URL         PMUrl      `json:"url"`
}

type PMUrl

type PMUrl struct {
	Raw      string    `json:"raw"`
	Protocol string    `json:"protocol"`
	Host     []string  `json:"host"`
	Path     []string  `json:"path"`
	Query    []PMQuery `json:"query"`
}

type Param added in v1.5.25

type Param struct {
	Key   string
	Value string
}

Param is a single URL parameter, consisting of a key and a value.

type ParamTable

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

type Params added in v1.5.25

type Params []Param

Params is a Param-slice, as returned by the router. The slice is ordered, the first URL parameter is also the first slice value. It is therefore safe to read values by the index.

type ParseToHttpResponse

type ParseToHttpResponse interface {
	Parse() ([]byte, error)
}

type Service

type Service[T any] interface {
	//返回描述,url的前缀,中间件
	Service() (describe, prefix string, middleware []T)
}

Directories

Path Synopsis
_example
gin

Jump to

Keyboard shortcuts

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