Apiware:一個輕鬆將net/http及fasthttp請求引數繫結到結構體的中介軟體

henrylee2cn發表於2016-10-22

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

相關文章