binding

package
v2.5.1+incompatible Latest Latest
Warning

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

Go to latest
Published: Jan 19, 2020 License: Apache-2.0 Imports: 19 Imported by: 0

README

binding GoDoc

A powerful HTTP request parameters binder that supports struct tag expression.

Example

func Example() {
	type InfoRequest struct {
		Name          string   `path:"name"`
		Year          []int    `query:"year"`
		Email         *string  `json:"email" vd:"email($)"`
		Friendly      bool     `json:"friendly"`
		Pie           float32  `json:"pie,required"`
		Hobby         []string `json:",required"`
		BodyNotFound  *int     `json:"BodyNotFound"`
		Authorization string   `header:"Authorization,required" vd:"$=='Basic 123456'"`
		SessionID     string   `cookie:"sessionid,required"`
		AutoBody      string
		AutoNotFound  *string
		TimeRFC3339   time.Time `query:"t"`
	}

	args := new(InfoRequest)
	binder := binding.New(nil)
	err := binder.BindAndValidate(args, requestExample(), new(testPathParams))

	fmt.Println("bind and validate result:")

	fmt.Printf("error: %v\n", err)

	b, _ := json.MarshalIndent(args, "", "	")
	fmt.Printf("args JSON string:\n%s\n", b)

	// Output:
	// request:
	// POST /info/henrylee2cn?year=2018&year=2019&t=2019-09-04T18%3A04%3A08%2B08%3A00 HTTP/1.1
	// Host: localhost
	// User-Agent: Go-http-client/1.1
	// Transfer-Encoding: chunked
	// Authorization: Basic 123456
	// Content-Type: application/json;charset=utf-8
	// Cookie: sessionid=987654
	//
	// 83
	// {"AutoBody":"autobody_test","Hobby":["Coding","Mountain climbing"],"email":"henrylee2cn@gmail.com","friendly":true,"pie":3.1415926}
	// 0
	//
	// bind and validate result:
	// error: <nil>
	// args JSON string:
	// {
	// 	"Name": "henrylee2cn",
	// 	"Year": [
	// 		2018,
	// 		2019
	// 	],
	// 	"email": "henrylee2cn@gmail.com",
	// 	"friendly": true,
	// 	"pie": 3.1415925,
	// 	"Hobby": [
	// 		"Coding",
	// 		"Mountain climbing"
	// 	],
	// 	"BodyNotFound": null,
	// 	"Authorization": "Basic 123456",
	// 	"SessionID": "987654",
	// 	"AutoBody": "autobody_test",
	// 	"AutoNotFound": null,
	// 	"TimeRFC3339": "2019-09-04T18:04:08+08:00"
	// }
}
...

Syntax

The parameter position in HTTP request:

expression renameable description
path:"$name" or path:"$name,required" Yes URL path parameter
query:"$name" or query:"$name,required" Yes URL query parameter
raw_body:"" or raw_body:"required" Yes The raw bytes of body
form:"$name" or form:"$name,required" Yes The field in body, support:
application/x-www-form-urlencoded,
multipart/form-data
protobuf:"...(raw syntax)" No The field in body, support:
application/x-protobuf
json:"$name" or json:"$name,required" No The field in body, support:
application/json
header:"$name" or header:"$name,required" Yes Header parameter
cookie:"$name" or cookie:"$name,required" Yes Cookie parameter
vd:"...(tagexpr validator syntax)" Yes The tagexpr expression of validator

NOTE:

  • "$name" is variable placeholder
  • If "$name" is empty, use the name of field
  • If "$name" is -, omit the field
  • Expression required or req indicates that the parameter is required
  • If no position is tagged, try bind parameters from the body when the request has body,
    otherwise try bind from the URL query
  • When there are multiple tags or no tags, the order in which to try to bind is:
    1. path
    2. form
    3. query
    4. cookie
    5. header
    6. protobuf
    7. json

Type Unmarshalor

TimeRFC3339-binding function is registered by default.

Register your own binding function for the specified type, e.g.:

MustRegTypeUnmarshal(reflect.TypeOf(time.Time{}), func(v string, emptyAsZero bool) (reflect.Value, error) {
	if v == "" && emptyAsZero {
		return reflect.ValueOf(time.Time{}), nil
	}
	t, err := time.Parse(time.RFC3339, v)
	if err != nil {
		return reflect.Value{}, err
	}
	return reflect.ValueOf(t), nil
})

Documentation

Overview

Example
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/bytedance/go-tagexpr/binding"
	"github.com/henrylee2cn/goutil/httpbody"
)

func main() {
	type InfoRequest struct {
		Name          string   `path:"name"`
		Year          []int    `query:"year"`
		Email         *string  `json:"email" vd:"email($)"`
		Friendly      bool     `json:"friendly"`
		Pie           float32  `json:"pie,required"`
		Hobby         []string `json:",required"`
		BodyNotFound  *int     `json:"BodyNotFound"`
		Authorization string   `header:"Authorization,required" vd:"$=='Basic 123456'"`
		SessionID     string   `cookie:"sessionid,required"`
		AutoBody      string
		AutoNotFound  *string
		TimeRFC3339   time.Time `query:"t"`
	}

	args := new(InfoRequest)
	binder := binding.New(nil)
	err := binder.BindAndValidate(args, requestExample(), new(testPathParams))

	fmt.Println("bind and validate result:")

	fmt.Printf("error: %v\n", err)

	b, _ := json.MarshalIndent(args, "", "	")
	fmt.Printf("args JSON string:\n%s\n", b)

}

func requestExample() *http.Request {
	contentType, bodyReader, _ := httpbody.NewJSONBody(map[string]interface{}{
		"email":    "henrylee2cn@gmail.com",
		"friendly": true,
		"pie":      3.1415926,
		"Hobby":    []string{"Coding", "Mountain climbing"},
		"AutoBody": "autobody_test",
	})
	header := make(http.Header)
	header.Add("Content-Type", contentType)
	header.Add("Authorization", "Basic 123456")
	cookies := []*http.Cookie{
		{Name: "sessionid", Value: "987654"},
	}
	req := newRequest("http://localhost/info/henrylee2cn?year=2018&year=2019&t=2019-09-04T18%3A04%3A08%2B08%3A00", header, cookies, bodyReader)
	req.Method = "POST"
	var w bytes.Buffer
	req.Write(&w)
	fmt.Printf("request:\n%s", strings.Replace(w.String(), "\r\n", "\n", -1))

	bodyReader.(*bytes.Reader).Seek(0, 0)
	return req
}
Output:

request:
POST /info/henrylee2cn?year=2018&year=2019&t=2019-09-04T18%3A04%3A08%2B08%3A00 HTTP/1.1
Host: localhost
User-Agent: Go-http-client/1.1
Transfer-Encoding: chunked
Authorization: Basic 123456
Content-Type: application/json;charset=utf-8
Cookie: sessionid=987654

83
{"AutoBody":"autobody_test","Hobby":["Coding","Mountain climbing"],"email":"henrylee2cn@gmail.com","friendly":true,"pie":3.1415926}
0

bind and validate result:
error: <nil>
args JSON string:
{
	"Name": "henrylee2cn",
	"Year": [
		2018,
		2019
	],
	"email": "henrylee2cn@gmail.com",
	"friendly": true,
	"pie": 3.1415925,
	"Hobby": [
		"Coding",
		"Mountain climbing"
	],
	"BodyNotFound": null,
	"Authorization": "Basic 123456",
	"SessionID": "987654",
	"AutoBody": "autobody_test",
	"AutoNotFound": null,
	"TimeRFC3339": "2019-09-04T18:04:08+08:00"
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bind

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

Bind binds the request parameters.

func BindAndValidate

func BindAndValidate(structPointer interface{}, req *http.Request, pathParams PathParams) error

BindAndValidate binds the request parameters and validates them if needed.

func MustRegTypeUnmarshal

func MustRegTypeUnmarshal(t reflect.Type, fn func(v string, emptyAsZero bool) (reflect.Value, error))

MustRegTypeUnmarshal registers unmarshalor function of type. NOTE:

panic if exist error.

func RegTypeUnmarshal

func RegTypeUnmarshal(t reflect.Type, fn func(v string, emptyAsZero bool) (reflect.Value, error)) error

RegTypeUnmarshal registers unmarshalor function of type.

func ResetJSONUnmarshaler

func ResetJSONUnmarshaler(verifyingRequired bool, fn func(data []byte, v interface{}) error)

ResetJSONUnmarshaler reset the JSON Unmarshal function. NOTE: verifyingRequired is true if the required tag is supported.

func SetErrorFactory

func SetErrorFactory(bindErrFactory, validatingErrFactory func(failField, msg string) error)

SetErrorFactory customizes the factory of validation error. NOTE:

If errFactory==nil, the default is used

func SetLooseZeroMode

func SetLooseZeroMode(enable bool)

SetLooseZeroMode if set to true, the empty string request parameter is bound to the zero value of parameter. NOTE:

The default is false;
Suitable for these parameter types: query/header/cookie/form .

func Validate

func Validate(value interface{}) error

Validate validates whether the fields of value is valid.

Types

type Binding

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

Binding binding and verification tool for http request

func Default

func Default() *Binding

Default returns the default binding. NOTE:

path tag name is 'path';
query tag name is 'query';
header tag name is 'header';
cookie tag name is 'cookie';
raw_body tag name is 'raw_body';
form tag name is 'form';
validator tag name is 'vd';
protobuf tag name is 'protobuf';
json tag name is 'json';
LooseZeroMode is false.

func New

func New(config *Config) *Binding

New creates a binding tool. NOTE:

Use default tag name for config fields that are empty

func (*Binding) Bind

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

Bind binds the request parameters.

func (*Binding) BindAndValidate

func (b *Binding) BindAndValidate(structPointer interface{}, req *http.Request, pathParams PathParams) error

BindAndValidate binds the request parameters and validates them if needed.

func (*Binding) SetErrorFactory

func (b *Binding) SetErrorFactory(bindErrFactory, validatingErrFactory func(failField, msg string) error) *Binding

SetErrorFactory customizes the factory of validation error. NOTE:

If errFactory==nil, the default is used

func (*Binding) SetLooseZeroMode

func (b *Binding) SetLooseZeroMode(enable bool) *Binding

SetLooseZeroMode if set to true, the empty string request parameter is bound to the zero value of parameter. NOTE:

The default is false;
Suitable for these parameter types: query/header/cookie/form .

func (*Binding) Validate

func (b *Binding) Validate(value interface{}) error

Validate validates whether the fields of value is valid.

type Config

type Config struct {
	// LooseZeroMode if set to true,
	// the empty string request parameter is bound to the zero value of parameter.
	// NOTE: Suitable for these parameter types: query/header/cookie/form .
	LooseZeroMode bool
	// PathParam use 'path' by default when empty
	PathParam string
	// Query use 'query' by default when empty
	Query string
	// Header use 'header' by default when empty
	Header string
	// Cookie use 'cookie' by default when empty
	Cookie string
	// RawBody use 'raw' by default when empty
	RawBody string
	// FormBody use 'form' by default when empty
	FormBody string
	// Validator use 'vd' by default when empty
	Validator string
	// contains filtered or unexported fields
}

Config the struct tag naming and so on

type Error

type Error struct {
	ErrType, FailField, Msg string
}

Error validate error

func (*Error) Error

func (e *Error) Error() string

Error implements error interface.

type PathParams

type PathParams interface {
	// Get returns the value of the first parameter which key matches the given name.
	// If no matching parameter is found, an empty string is returned.
	Get(name string) (string, bool)
}

PathParams parameter acquisition interface on the URL path

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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