apiware

package module
v0.0.0-...-a1b8eb8 Latest Latest
Warning

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

Go to latest
Published: Dec 20, 2016 License: Apache-2.0 Imports: 14 Imported by: 0

README

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 and so on
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) the custom error for binding or validating
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

Documentation

Overview

Package apiware provides a tools which can bind the http/fasthttp request params to the structure and validate.

Copyright 2016 HenryLee. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Param tag value description:

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")| the custom error for binding or validating

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

List of supported param value 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 |

Index

Constants

View Source
const (
	ValidationErrorValueNotSet = (1<<16 + iota)
	ValidationErrorValueTooSmall
	ValidationErrorValueTooBig
	ValidationErrorValueTooShort
	ValidationErrorValueTooLong
	ValidationErrorValueNotMatch
)
View Source
const (
	TAG_PARAM        = "param"  //request param tag name
	TAG_REGEXP       = "regexp" //regexp validate tag name(optio)
	TAG_ERR          = "err"    //the custom error for binding or validating
	TAG_IGNORE_PARAM = "-"      //ignore request param tag value

	MB = 1 << 20 // 1MB

)

Variables

View Source
var (
	// values for tag 'in'
	TagInValues = map[string]bool{
		"path":     true,
		"query":    true,
		"formData": true,
		"body":     true,
		"header":   true,
		"cookie":   true,
	}
)

Functions

func Bind

func Bind(
	structPointer interface{},
	req *http.Request,
	pathParams KV,
) error

Bind binds the net/http request params to the `structPointer` param and validate it. note: structPointer must be struct pointer.

func BindByName

func BindByName(
	paramsAPIName string,
	req *http.Request,
	pathParams KV,
) (
	interface{},
	error,
)

BindByName binds the net/http request params to a new struct and validate it.

func ConvertAssign

func ConvertAssign(dest reflect.Value, src ...string) (err error)

Type conversions for request params.

ConvertAssign copies to dest the value in src, converting it if possible. An error is returned if the copy would result in loss of information. dest should be a pointer type.

func FasthttpBind

func FasthttpBind(
	structPointer interface{},
	req *fasthttp.RequestCtx,
	pathParams KV,
) error

FasthttpBind binds the net/http request params to the `structPointer` param and validate it. note: structPointer must be struct pointer.

func FasthttpBindByName

func FasthttpBindByName(
	paramsAPIName string,
	req *fasthttp.RequestCtx,
	pathParams KV,
) (
	interface{},
	error,
)

FasthttpBindByName binds the net/http request params to a new struct and validate it.

func NewValidationError

func NewValidationError(id int, field string) error

NewValidationError returns a new validation error with the specified id and text. The id's purpose is to distinguish different validation error types. Built-in validation error ids start at 65536, so you should keep your custom ids under that value.

func ParseTags

func ParseTags(s string) map[string]string

func Register

func Register(
	structPointer interface{},
	paramNameFunc ParamNameFunc,
	bodyDecodeFunc BodyDecodeFunc,
) error

Register is similar to a `NewParamsAPI`, but only return error. Parse and store the struct object, requires a struct pointer, if `paramNameFunc` is nil, `paramNameFunc=toSnake`, if `bodyDecodeFunc` is nil, `bodyDecodeFunc=bodyJONS`,

func SetParamsAPI

func SetParamsAPI(m *ParamsAPI)

SetParamsAPI caches `*ParamsAPI`

Types

type Apiware

type Apiware struct {
	ParamNameFunc
	PathDecodeFunc
	BodyDecodeFunc
}

func New

func New(pathDecodeFunc PathDecodeFunc, bodyDecodeFunc BodyDecodeFunc, paramNameFunc ParamNameFunc) *Apiware

Create a new apiware engine. Parse and store the struct object, requires a struct pointer, if `paramNameFunc` is nil, `paramNameFunc=toSnake`, if `bodyDecodeFunc` is nil, `bodyDecodeFunc=bodyJONS`,

func (*Apiware) Bind

func (a *Apiware) Bind(
	structPointer interface{},
	req *http.Request,
	pattern string,
) error

Bind the net/http request params to the structure and validate. note: structPointer must be structure pointer.

func (*Apiware) FasthttpBind

func (a *Apiware) FasthttpBind(structPointer interface{}, reqCtx *fasthttp.RequestCtx, pattern string) (err error)

FasthttpBind the fasthttp request params to the structure and validate. note: structPointer must be structure pointer.

func (*Apiware) Register

func (a *Apiware) Register(structPointers ...interface{}) error

Check whether structs meet the requirements of apiware, and register them. note: requires a structure pointer.

type BodyDecodeFunc

type BodyDecodeFunc func(dest reflect.Value, body []byte) error

Decode params from request body

type Error

type Error struct {
	Api    string `json:"api"`
	Param  string `json:"param"`
	Reason string `json:"reason"`
}

func NewError

func NewError(api string, param string, reason string) *Error

func (*Error) Error

func (e *Error) Error() string

type KV

type KV interface {
	Get(k string) (v string, found bool)
}

type Map

type Map map[string]string

func (Map) Get

func (m Map) Get(k string) (string, bool)

type Param

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

use the struct field to define a request parameter model

func (*Param) APIName

func (param *Param) APIName() string

APIName gets ParamsAPI name

func (*Param) Description

func (param *Param) Description() string

Description gets the description value for the param

func (*Param) In

func (param *Param) In() string

In get the type value for the param

func (*Param) IsFile

func (param *Param) IsFile() bool

IsFile tests if the param is type *multipart.FileHeader

func (*Param) IsRequired

func (param *Param) IsRequired() bool

IsRequired tests if the param is declared

func (*Param) Name

func (param *Param) Name() string

Name gets parameter field name

func (*Param) Raw

func (param *Param) Raw() interface{}

Raw gets the param's original value

type ParamNameFunc

type ParamNameFunc func(fieldName string) (paramName string)

Create param name from struct param name

type ParamsAPI

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

ParamsAPI defines a parameter model for an web api.

func GetParamsAPI

func GetParamsAPI(paramsAPIName string) (*ParamsAPI, error)

GetParamsAPI gets the `*ParamsAPI` object according to the type name

func NewParamsAPI

func NewParamsAPI(
	structPointer interface{},
	paramNameFunc ParamNameFunc,
	bodyDecodeFunc BodyDecodeFunc,
) (
	*ParamsAPI,
	error,
)

NewParamsAPI parses and store the struct object, requires a struct pointer, if `paramNameFunc` is nil, `paramNameFunc=toSnake`, if `bodyDecodeFunc` is nil, `bodyDecodeFunc=bodyJONS`,

func (*ParamsAPI) BindAt

func (paramsAPI *ParamsAPI) BindAt(
	structPointer interface{},
	req *http.Request,
	pathParams KV,
) error

BindAt binds the net/http request params to a struct pointer and validate it. note: structPointer must be struct pointer.

func (*ParamsAPI) BindFields

func (paramsAPI *ParamsAPI) BindFields(
	fields []reflect.Value,
	req *http.Request,
	pathParams KV,
) (
	err error,
)

BindFields binds the net/http request params to a struct and validate it. Must ensure that the param `fields` matches `paramsAPI.params`.

func (*ParamsAPI) BindNew

func (paramsAPI *ParamsAPI) BindNew(
	req *http.Request,
	pathParams KV,
) (
	interface{},
	error,
)

BindNew binds the net/http request params to a struct pointer and validate it.

func (*ParamsAPI) FasthttpBindAt

func (paramsAPI *ParamsAPI) FasthttpBindAt(
	structPointer interface{},
	req *fasthttp.RequestCtx,
	pathParams KV,
) error

FasthttpBindAt binds the net/http request params to a struct pointer and validate it. note: structPointer must be struct pointer.

func (*ParamsAPI) FasthttpBindFields

func (paramsAPI *ParamsAPI) FasthttpBindFields(
	fields []reflect.Value,
	req *fasthttp.RequestCtx,
	pathParams KV,
) (
	err error,
)

FasthttpBindFields binds the net/http request params to a struct and validate it. Must ensure that the param `fields` matches `paramsAPI.params`.

func (*ParamsAPI) FasthttpBindNew

func (paramsAPI *ParamsAPI) FasthttpBindNew(
	req *fasthttp.RequestCtx,
	pathParams KV,
) (
	interface{},
	error,
)

FasthttpBindNew binds the net/http request params to a struct pointer and validate it.

func (*ParamsAPI) FasthttpRawBind

func (paramsAPI *ParamsAPI) FasthttpRawBind(
	req *fasthttp.RequestCtx,
	pathParams KV,
) (
	interface{},
	error,
)

RawBind binds the net/http request params to the original struct pointer and validate it.

func (*ParamsAPI) MaxMemory

func (paramsAPI *ParamsAPI) MaxMemory() int64

MaxMemory gets maxMemory when request Content-Type is multipart/form-data, the max memory for body.

func (*ParamsAPI) Name

func (paramsAPI *ParamsAPI) Name() string

Name gets the name

func (*ParamsAPI) NewReceiver

func (paramsAPI *ParamsAPI) NewReceiver() (interface{}, []reflect.Value)

NewReceiver creates a new struct pointer and the field's values for its receive parameterste it.

func (*ParamsAPI) Number

func (paramsAPI *ParamsAPI) Number() int

Number returns the number of parameters to be bound

func (*ParamsAPI) Params

func (paramsAPI *ParamsAPI) Params() []*Param

Params gets the parameter information

func (*ParamsAPI) Raw

func (paramsAPI *ParamsAPI) Raw() interface{}

Raw returns the ParamsAPI's original value

func (*ParamsAPI) RawBind

func (paramsAPI *ParamsAPI) RawBind(
	req *http.Request,
	pathParams KV,
) (
	interface{},
	error,
)

RawBind binds the net/http request params to the original struct pointer and validate it.

func (*ParamsAPI) SetMaxMemory

func (paramsAPI *ParamsAPI) SetMaxMemory(maxMemory int64)

SetMaxMemory sets maxMemory for the request which Content-Type is multipart/form-data.

type PathDecodeFunc

type PathDecodeFunc func(urlPath, pattern string) (pathParams KV)

Parse path params function, return pathParams of KV type

type Schema

type Schema struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Schema is a collection of ParamsAPI

type ValidationError

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

Validation error type

func (*ValidationError) Error

func (e *ValidationError) Error() string

func (*ValidationError) Field

func (e *ValidationError) Field() string

func (*ValidationError) Kind

func (e *ValidationError) Kind() int

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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