binding

package
v2.2.1+incompatible Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2019 License: Apache-2.0 Imports: 17 Imported by: 0

README

binding GoDoc

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

Example

package binding_test

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

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

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
	}

	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 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
	// }
}
...

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, the order in which to try to bind is:
    1. path
    2. query
    3. raw_body
    4. form
    5. protobuf
    6. json
    7. header
    8. cookie

Documentation

Overview

Example
package main

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

	"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
	}

	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", 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 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
}

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 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 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'.

func New

func New(tagNames *TagNames) *Binding

New creates a binding tool. NOTE:

Use default tag name for tagNames 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) Validate

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

Validate validates whether the fields of value is valid.

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

type TagNames

type TagNames struct {
	// 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
}

TagNames struct tag naming

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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