mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-19 15:57:48 +08:00
commit
661abaa3b9
20
README.md
20
README.md
@ -17,7 +17,6 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi
|
|||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Prerequisite](#prerequisite)
|
|
||||||
- [Quick start](#quick-start)
|
- [Quick start](#quick-start)
|
||||||
- [Benchmarks](#benchmarks)
|
- [Benchmarks](#benchmarks)
|
||||||
- [Gin v1.stable](#gin-v1-stable)
|
- [Gin v1.stable](#gin-v1-stable)
|
||||||
@ -584,7 +583,7 @@ func main() {
|
|||||||
|
|
||||||
To bind a request body into a type, use model binding. We currently support binding of JSON, XML, YAML and standard form values (foo=bar&boo=baz).
|
To bind a request body into a type, use model binding. We currently support binding of JSON, XML, YAML and standard form values (foo=bar&boo=baz).
|
||||||
|
|
||||||
Gin uses [**go-playground/validator.v8**](https://github.com/go-playground/validator) for validation. Check the full docs on tags usage [here](http://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Baked_In_Validators_and_Tags).
|
Gin uses [**go-playground/validator/v10**](https://github.com/go-playground/validator) for validation. Check the full docs on tags usage [here](https://godoc.org/github.com/go-playground/validator#hdr-Baked_In_Validators_and_Tags).
|
||||||
|
|
||||||
Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set `json:"fieldname"`.
|
Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set `json:"fieldname"`.
|
||||||
|
|
||||||
@ -704,25 +703,22 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
"gopkg.in/go-playground/validator.v8"
|
"gopkg.in/go-playground/validator.v10"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Booking contains binded and validated data.
|
// Booking contains binded and validated data.
|
||||||
type Booking struct {
|
type Booking struct {
|
||||||
CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
|
CheckIn time.Time `form:"check_in" binding:"required" time_format:"2006-01-02"`
|
||||||
CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
|
CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func bookableDate(
|
var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
|
||||||
v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
|
date, ok := fl.Field().Interface().(time.Time)
|
||||||
field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
|
if ok {
|
||||||
) bool {
|
|
||||||
if date, ok := field.Interface().(time.Time); ok {
|
|
||||||
today := time.Now()
|
today := time.Now()
|
||||||
if today.After(date) {
|
if today.After(date) {
|
||||||
return false
|
return false
|
||||||
@ -756,8 +752,8 @@ func getBookable(c *gin.Context) {
|
|||||||
$ curl "localhost:8085/bookable?check_in=2018-04-16&check_out=2018-04-17"
|
$ curl "localhost:8085/bookable?check_in=2018-04-16&check_out=2018-04-17"
|
||||||
{"message":"Booking dates are valid!"}
|
{"message":"Booking dates are valid!"}
|
||||||
|
|
||||||
$ curl "localhost:8085/bookable?check_in=2018-03-08&check_out=2018-03-09"
|
$ curl "localhost:8085/bookable?check_in=2018-03-10&check_out=2018-03-09"
|
||||||
{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"}
|
{"error":"Key: 'Booking.CheckOut' Error:Field validation for 'CheckOut' failed on the 'gtfield' tag"}
|
||||||
```
|
```
|
||||||
|
|
||||||
[Struct level validations](https://github.com/go-playground/validator/releases/tag/v8.7) can also be registered this way.
|
[Struct level validations](https://github.com/go-playground/validator/releases/tag/v8.7) can also be registered this way.
|
||||||
|
59
tree.go
59
tree.go
@ -425,8 +425,35 @@ func (n *node) getValue(path string, po Params, unescape bool) (value nodeValue)
|
|||||||
walk: // Outer loop for walking the tree
|
walk: // Outer loop for walking the tree
|
||||||
for {
|
for {
|
||||||
prefix := n.path
|
prefix := n.path
|
||||||
if len(path) > len(prefix) {
|
if path == prefix {
|
||||||
if path[:len(prefix)] == prefix {
|
// We should have reached the node containing the handle.
|
||||||
|
// Check if this node has a handle registered.
|
||||||
|
if value.handlers = n.handlers; value.handlers != nil {
|
||||||
|
value.fullPath = n.fullPath
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if path == "/" && n.wildChild && n.nType != root {
|
||||||
|
value.tsr = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// No handle found. Check if a handle for this path + a
|
||||||
|
// trailing slash exists for trailing slash recommendation
|
||||||
|
indices := n.indices
|
||||||
|
for i, max := 0, len(indices); i < max; i++ {
|
||||||
|
if indices[i] == '/' {
|
||||||
|
n = n.children[i]
|
||||||
|
value.tsr = (len(n.path) == 1 && n.handlers != nil) ||
|
||||||
|
(n.nType == catchAll && n.children[0].handlers != nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(path) > len(prefix) && path[:len(prefix)] == prefix {
|
||||||
path = path[len(prefix):]
|
path = path[len(prefix):]
|
||||||
// If this node does not have a wildcard (param or catchAll)
|
// If this node does not have a wildcard (param or catchAll)
|
||||||
// child, we can just look up the next child node and continue
|
// child, we can just look up the next child node and continue
|
||||||
@ -500,7 +527,6 @@ walk: // Outer loop for walking the tree
|
|||||||
n = n.children[0]
|
n = n.children[0]
|
||||||
value.tsr = n.path == "/" && n.handlers != nil
|
value.tsr = n.path == "/" && n.handlers != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
case catchAll:
|
case catchAll:
|
||||||
@ -528,33 +554,6 @@ walk: // Outer loop for walking the tree
|
|||||||
panic("invalid node type")
|
panic("invalid node type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if path == prefix {
|
|
||||||
// We should have reached the node containing the handle.
|
|
||||||
// Check if this node has a handle registered.
|
|
||||||
if value.handlers = n.handlers; value.handlers != nil {
|
|
||||||
value.fullPath = n.fullPath
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if path == "/" && n.wildChild && n.nType != root {
|
|
||||||
value.tsr = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// No handle found. Check if a handle for this path + a
|
|
||||||
// trailing slash exists for trailing slash recommendation
|
|
||||||
indices := n.indices
|
|
||||||
for i, max := 0, len(indices); i < max; i++ {
|
|
||||||
if indices[i] == '/' {
|
|
||||||
n = n.children[i]
|
|
||||||
value.tsr = (len(n.path) == 1 && n.handlers != nil) ||
|
|
||||||
(n.nType == catchAll && n.children[0].handlers != nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing found. We can recommend to redirect to the same URL with an
|
// Nothing found. We can recommend to redirect to the same URL with an
|
||||||
// extra trailing slash if a leaf exists for that path
|
// extra trailing slash if a leaf exists for that path
|
||||||
|
Loading…
x
Reference in New Issue
Block a user