mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-19 07:38:57 +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
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Prerequisite](#prerequisite)
|
||||
- [Quick start](#quick-start)
|
||||
- [Benchmarks](#benchmarks)
|
||||
- [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).
|
||||
|
||||
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"`.
|
||||
|
||||
@ -704,25 +703,22 @@ package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
"gopkg.in/go-playground/validator.v8"
|
||||
"gopkg.in/go-playground/validator.v10"
|
||||
)
|
||||
|
||||
// Booking contains binded and validated data.
|
||||
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"`
|
||||
}
|
||||
|
||||
func bookableDate(
|
||||
v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
|
||||
field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
|
||||
) bool {
|
||||
if date, ok := field.Interface().(time.Time); ok {
|
||||
var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
|
||||
date, ok := fl.Field().Interface().(time.Time)
|
||||
if ok {
|
||||
today := time.Now()
|
||||
if today.After(date) {
|
||||
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"
|
||||
{"message":"Booking dates are valid!"}
|
||||
|
||||
$ curl "localhost:8085/bookable?check_in=2018-03-08&check_out=2018-03-09"
|
||||
{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"}
|
||||
$ curl "localhost:8085/bookable?check_in=2018-03-10&check_out=2018-03-09"
|
||||
{"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.
|
||||
|
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
|
||||
for {
|
||||
prefix := n.path
|
||||
if len(path) > len(prefix) {
|
||||
if path[:len(prefix)] == prefix {
|
||||
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
|
||||
}
|
||||
|
||||
if len(path) > len(prefix) && path[:len(prefix)] == prefix {
|
||||
path = path[len(prefix):]
|
||||
// If this node does not have a wildcard (param or catchAll)
|
||||
// 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]
|
||||
value.tsr = n.path == "/" && n.handlers != nil
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
case catchAll:
|
||||
@ -528,33 +554,6 @@ walk: // Outer loop for walking the tree
|
||||
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
|
||||
// extra trailing slash if a leaf exists for that path
|
||||
|
Loading…
x
Reference in New Issue
Block a user