新手问题 Apiware:一个轻松将net/http及fasthttp请求参数绑定到结构体的中间件

henrylee2cn · 2016年10月22日 · 411 次阅读

Apiware GoDoc

Apiware binds the specified parameters of the Golang net/http and fasthttp requests to the structure and verifies the validity of the parameter values.

It is suggested that you can use the struct as the Handler of the web framework, and use the middleware to quickly bind the request parameters, saving a lot of parameter type conversion and validity verification. At the same time through the struct tag, create swagger json configuration file, easy to create api document services.

Apiware 将 Go 语言net/httpfasthttp请求的指定参数绑定到结构体,并验证参数值的合法性。 建议您可以使用结构体作为 web 框架的 Handler,并用该中间件快速绑定请求参数,节省了大量参数类型转换与有效性验证的工作。同时还可以通过该结构体标签,创建 swagger 的 json 配置文件,轻松创建 api 文档服务。

Demo 示例

package main

import (
    "encoding/json"
    "github.com/henrylee2cn/apiware"
    // "mime/multipart"
    "net/http"
    "strings"
)

type TestApiware struct {
    Id           int         `param:"in(path),required,desc(ID),range(1:2)"`
    Num          float32     `param:"in(query),name(n),range(0.1:10.19)"`
    Title        string      `param:"in(query),nonzero"`
    Paragraph    []string    `param:"in(query),name(p),len(1:10)" regexp:"(^[\\w]*$)"`
    Cookie       http.Cookie `param:"in(cookie),name(apiwareid)"`
    CookieString string      `param:"in(cookie),name(apiwareid)"`
    // Picture   multipart.FileHeader `param:"in(formData),name(pic),maxmb(30)"`
}

var myApiware = apiware.New(pathDecodeFunc, nil, nil)

var pattern = "/test/:id"

func pathDecodeFunc(urlPath, pattern string) apiware.KV {
    idx := map[int]string{}
    for k, v := range strings.Split(pattern, "/") {
        if !strings.HasPrefix(v, ":") {
            continue
        }
        idx[k] = v[1:]
    }
    pathParams := make(map[string]string, len(idx))
    for k, v := range strings.Split(urlPath, "/") {
        name, ok := idx[k]
        if !ok {
            continue
        }
        pathParams[name] = v
    }
    return apiware.Map(pathParams)
}

func testHandler(resp http.ResponseWriter, req *http.Request) {
    // set cookies
    http.SetCookie(resp, &http.Cookie{
        Name:  "apiwareid",
        Value: "http_henrylee2cn",
    })

    // bind params
    params := new(TestApiware)
    err := myApiware.Bind(params, req, pattern)
    b, _ := json.MarshalIndent(params, "", " ")
    if err != nil {
        resp.WriteHeader(http.StatusBadRequest)
        resp.Write(append([]byte(err.Error()+"\n"), b...))
    } else {
        resp.WriteHeader(http.StatusOK)
        resp.Write(b)
    }
}

func main() {
    // Check whether `testHandler` meet the requirements of apiware, and register it
    err := myApiware.Register(new(TestApiware))
    if err != nil {
        panic(err)
    }

    // server
    http.HandleFunc("/test/0", testHandler)
    http.HandleFunc("/test/1", testHandler)
    http.HandleFunc("/test/1.1", testHandler)
    http.HandleFunc("/test/2", testHandler)
    http.HandleFunc("/test/3", testHandler)
    http.ListenAndServe(":8080", nil)
}

Struct&Tag 结构体及其标签

tag key required value desc
param in only one path (position of param) if required is unsetted, auto set it. e.g. url: "http://www.abc.com/a/path}{"
param in only one query (position of param) e.g. url: "http://www.abc.com/a?b=query}{"
param in only one formData (position of param) e.g. "request body: a=123&b={formData}"
param in only one body (position of param) request body can be any content
param in only one header (position of param) request header info
param in only one cookie (position of param) request cookie info, support: http.Cookie,fasthttp.Cookie,string,[]byte
param name no (e.g. "id") specify request param`s name
param required no required request param is required
param desc no (e.g. "id") request param description
param len no (e.g. 3:6, 3) length range of param's value
param range no (e.g. 0:10) numerical range of param's value
param nonzero no nonzero param`s value can not be zero
param maxmb no (e.g. 32) when request Content-Type is multipart/form-data, the max memory for body.(multi-param, whichever is greater)
regexp no (e.g. "^\w+$") param value can not be null
err no (e.g. "incorrect password format") customize the prompt for validation error

NOTES:

  • the binding object must be a struct pointer
  • the binding struct's field can not be a pointer
  • regexp or param tag is only usable when param:"type(xxx)" is exist
  • if the param tag is not exist, anonymous field will be parsed
  • when the param's position(in) is formData and the field's type is multipart.FileHeader, the param receives file uploaded
  • if param's position(in) is cookie, field's type must be http.Cookie
  • param tags in(formData) and in(body) can not exist at the same time
  • there should not be more than one in(body) param tag

Field Types 结构体字段类型

base slice special
string [] string [][] byte
byte [] byte [][] uint8
uint8 [] uint8 multipart.FileHeader (only for formData param)
bool [] bool http.Cookie (only for net/http's cookie param)
int [] int fasthttp.Cookie (only for fasthttp's cookie param)
int8 [] int8 struct (struct type only for body param or as an anonymous field to extend params)
int16 [] int16
int32 [] int32
int64 [] int64
uint8 [] uint8
uint16 [] uint16
uint32 [] uint32
uint64 [] uint64
float32 [] float32
float64 [] float64

Source code

https://github.com/henrylee2cn/apiware

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册