remove internal.Params

This commit is contained in:
thinkerou 2018-11-03 16:16:22 +08:00
parent 91e3335932
commit eb8befa8c3
10 changed files with 80 additions and 101 deletions

View File

@ -4,11 +4,7 @@
package binding package binding
import ( import "net/http"
"net/http"
"github.com/gin-gonic/gin/internal"
)
// Content-Type MIME of the most common data formats. // Content-Type MIME of the most common data formats.
const ( const (
@ -43,7 +39,7 @@ type BindingBody interface {
// but it read the Params. // but it read the Params.
type BindingUri interface { type BindingUri interface {
Name() string Name() string
BindUri(internal.Params, interface{}) error BindUri(map[string][]string, interface{}) error
} }
// StructValidator is the minimal interface which needs to be implemented in // StructValidator is the minimal interface which needs to be implemented in

View File

@ -14,7 +14,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/gin-gonic/gin/internal"
"github.com/gin-gonic/gin/testdata/protoexample" "github.com/gin-gonic/gin/testdata/protoexample"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -654,8 +653,9 @@ func TestUriBinding(t *testing.T) {
Name string `uri:"name"` Name string `uri:"name"`
} }
var tag Tag var tag Tag
params := internal.Params{internal.Param{Key: "name", Value: "thinkerou"}} m := make(map[string][]string)
assert.NoError(t, b.BindUri(params, &tag)) m["name"] = []string{"thinkerou"}
assert.NoError(t, b.BindUri(m, &tag))
assert.Equal(t, "thinkerou", tag.Name) assert.Equal(t, "thinkerou", tag.Name)
} }

View File

@ -10,15 +10,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/gin-gonic/gin/internal"
) )
func mapUri(ptr interface{}, ps internal.Params) error { func mapUri(ptr interface{}, m map[string][]string) error {
m := make(map[string][]string)
for _, v := range ps {
m[v.Key] = []string{v.Value}
}
return mapFormByTag(ptr, m, "uri") return mapFormByTag(ptr, m, "uri")
} }

View File

@ -4,16 +4,14 @@
package binding package binding
import "github.com/gin-gonic/gin/internal"
type uriBinding struct{} type uriBinding struct{}
func (uriBinding) Name() string { func (uriBinding) Name() string {
return "uri" return "uri"
} }
func (uriBinding) BindUri(p internal.Params, obj interface{}) error { func (uriBinding) BindUri(m map[string][]string, obj interface{}) error {
if err := mapUri(obj, p); err != nil { if err := mapUri(obj, m); err != nil {
return err return err
} }
return validate(obj) return validate(obj)

View File

@ -19,7 +19,6 @@ import (
"github.com/gin-contrib/sse" "github.com/gin-contrib/sse"
"github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/binding"
"github.com/gin-gonic/gin/internal"
"github.com/gin-gonic/gin/render" "github.com/gin-gonic/gin/render"
) )
@ -44,7 +43,7 @@ type Context struct {
Request *http.Request Request *http.Request
Writer ResponseWriter Writer ResponseWriter
Params internal.Params Params Params
handlers HandlersChain handlers HandlersChain
index int8 index int8
@ -566,7 +565,11 @@ func (c *Context) ShouldBindQuery(obj interface{}) error {
// ShouldBindUri binds the passed struct pointer using the specified binding engine. // ShouldBindUri binds the passed struct pointer using the specified binding engine.
func (c *Context) ShouldBindUri(obj interface{}) error { func (c *Context) ShouldBindUri(obj interface{}) error {
return binding.Uri.BindUri(c.Params, obj) m := make(map[string][]string)
for _, v := range c.Params {
m[v.Key] = []string{v.Value}
}
return binding.Uri.BindUri(m, obj)
} }
// ShouldBindWith binds the passed struct pointer using the specified binding engine. // ShouldBindWith binds the passed struct pointer using the specified binding engine.

View File

@ -20,7 +20,6 @@ import (
"github.com/gin-contrib/sse" "github.com/gin-contrib/sse"
"github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/binding"
"github.com/gin-gonic/gin/internal"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -159,7 +158,7 @@ func TestContextReset(t *testing.T) {
c.index = 2 c.index = 2
c.Writer = &responseWriter{ResponseWriter: httptest.NewRecorder()} c.Writer = &responseWriter{ResponseWriter: httptest.NewRecorder()}
c.Params = internal.Params{internal.Param{}} c.Params = Params{Param{}}
c.Error(errors.New("test")) c.Error(errors.New("test"))
c.Set("foo", "bar") c.Set("foo", "bar")
c.reset() c.reset()
@ -317,7 +316,7 @@ func TestContextCopy(t *testing.T) {
c.index = 2 c.index = 2
c.Request, _ = http.NewRequest("POST", "/hola", nil) c.Request, _ = http.NewRequest("POST", "/hola", nil)
c.handlers = HandlersChain{func(c *Context) {}} c.handlers = HandlersChain{func(c *Context) {}}
c.Params = internal.Params{internal.Param{Key: "foo", Value: "bar"}} c.Params = Params{Param{Key: "foo", Value: "bar"}}
c.Set("foo", "bar") c.Set("foo", "bar")
cp := c.Copy() cp := c.Copy()

View File

@ -14,8 +14,6 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/gin-gonic/gin/internal"
) )
type route struct { type route struct {
@ -339,9 +337,9 @@ func TestGithubAPI(t *testing.T) {
} }
} }
func exampleFromPath(path string) (string, internal.Params) { func exampleFromPath(path string) (string, Params) {
output := new(bytes.Buffer) output := new(bytes.Buffer)
params := make(internal.Params, 0, 6) params := make(Params, 0, 6)
start := -1 start := -1
for i, c := range path { for i, c := range path {
if c == ':' { if c == ':' {
@ -350,7 +348,7 @@ func exampleFromPath(path string) (string, internal.Params) {
if start >= 0 { if start >= 0 {
if c == '/' { if c == '/' {
value := fmt.Sprint(rand.Intn(100000)) value := fmt.Sprint(rand.Intn(100000))
params = append(params, internal.Param{ params = append(params, Param{
Key: path[start:i], Key: path[start:i],
Value: value, Value: value,
}) })
@ -364,7 +362,7 @@ func exampleFromPath(path string) (string, internal.Params) {
} }
if start >= 0 { if start >= 0 {
value := fmt.Sprint(rand.Intn(100000)) value := fmt.Sprint(rand.Intn(100000))
params = append(params, internal.Param{ params = append(params, Param{
Key: path[start:], Key: path[start:],
Value: value, Value: value,
}) })

View File

@ -1,34 +0,0 @@
// Copyright 2018 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package internal
// Param is a single URL parameter, consisting of a key and a value.
type Param struct {
Key string
Value string
}
// Params is a Param-slice, as returned by the router.
// The slice is ordered, the first URL parameter is also the first slice value.
// It is therefore safe to read values by the index.
type Params []Param
// Get returns the value of the first Param which key matches the given name.
// If no matching Param is found, an empty string is returned.
func (ps Params) Get(name string) (string, bool) {
for _, entry := range ps {
if entry.Key == name {
return entry.Value, true
}
}
return "", false
}
// ByName returns the value of the first Param which key matches the given name.
// If no matching Param is found, an empty string is returned.
func (ps Params) ByName(name string) (va string) {
va, _ = ps.Get(name)
return
}

37
tree.go
View File

@ -8,10 +8,37 @@ import (
"net/url" "net/url"
"strings" "strings"
"unicode" "unicode"
"github.com/gin-gonic/gin/internal"
) )
// Param is a single URL parameter, consisting of a key and a value.
type Param struct {
Key string
Value string
}
// Params is a Param-slice, as returned by the router.
// The slice is ordered, the first URL parameter is also the first slice value.
// It is therefore safe to read values by the index.
type Params []Param
// Get returns the value of the first Param which key matches the given name.
// If no matching Param is found, an empty string is returned.
func (ps Params) Get(name string) (string, bool) {
for _, entry := range ps {
if entry.Key == name {
return entry.Value, true
}
}
return "", false
}
// ByName returns the value of the first Param which key matches the given name.
// If no matching Param is found, an empty string is returned.
func (ps Params) ByName(name string) (va string) {
va, _ = ps.Get(name)
return
}
type methodTree struct { type methodTree struct {
method string method string
root *node root *node
@ -342,7 +369,7 @@ func (n *node) insertChild(numParams uint8, path string, fullPath string, handle
// If no handle can be found, a TSR (trailing slash redirect) recommendation is // If no handle can be found, a TSR (trailing slash redirect) recommendation is
// made if a handle exists with an extra (without the) trailing slash for the // made if a handle exists with an extra (without the) trailing slash for the
// given path. // given path.
func (n *node) getValue(path string, po internal.Params, unescape bool) (handlers HandlersChain, p internal.Params, tsr bool) { func (n *node) getValue(path string, po Params, unescape bool) (handlers HandlersChain, p Params, tsr bool) {
p = po p = po
walk: // Outer loop for walking the tree walk: // Outer loop for walking the tree
for { for {
@ -380,7 +407,7 @@ walk: // Outer loop for walking the tree
// save param value // save param value
if cap(p) < int(n.maxParams) { if cap(p) < int(n.maxParams) {
p = make(internal.Params, 0, n.maxParams) p = make(Params, 0, n.maxParams)
} }
i := len(p) i := len(p)
p = p[:i+1] // expand slice within preallocated capacity p = p[:i+1] // expand slice within preallocated capacity
@ -423,7 +450,7 @@ walk: // Outer loop for walking the tree
case catchAll: case catchAll:
// save param value // save param value
if cap(p) < int(n.maxParams) { if cap(p) < int(n.maxParams) {
p = make(internal.Params, 0, n.maxParams) p = make(Params, 0, n.maxParams)
} }
i := len(p) i := len(p)
p = p[:i+1] // expand slice within preallocated capacity p = p[:i+1] // expand slice within preallocated capacity

View File

@ -10,8 +10,6 @@ import (
"regexp" "regexp"
"strings" "strings"
"testing" "testing"
"github.com/gin-gonic/gin/internal"
) )
// Used as a workaround since we can't compare functions or their addressses // Used as a workaround since we can't compare functions or their addressses
@ -27,7 +25,7 @@ type testRequests []struct {
path string path string
nilHandler bool nilHandler bool
route string route string
ps internal.Params ps Params
} }
func checkRequests(t *testing.T, tree *node, requests testRequests, unescapes ...bool) { func checkRequests(t *testing.T, tree *node, requests testRequests, unescapes ...bool) {
@ -172,19 +170,19 @@ func TestTreeWildcard(t *testing.T) {
checkRequests(t, tree, testRequests{ checkRequests(t, tree, testRequests{
{"/", false, "/", nil}, {"/", false, "/", nil},
{"/cmd/test/", false, "/cmd/:tool/", internal.Params{internal.Param{Key: "tool", Value: "test"}}}, {"/cmd/test/", false, "/cmd/:tool/", Params{Param{Key: "tool", Value: "test"}}},
{"/cmd/test", true, "", internal.Params{internal.Param{Key: "tool", Value: "test"}}}, {"/cmd/test", true, "", Params{Param{Key: "tool", Value: "test"}}},
{"/cmd/test/3", false, "/cmd/:tool/:sub", internal.Params{internal.Param{Key: "tool", Value: "test"}, internal.Param{Key: "sub", Value: "3"}}}, {"/cmd/test/3", false, "/cmd/:tool/:sub", Params{Param{Key: "tool", Value: "test"}, Param{Key: "sub", Value: "3"}}},
{"/src/", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/"}}}, {"/src/", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/"}}},
{"/src/some/file.png", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/some/file.png"}}}, {"/src/some/file.png", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/some/file.png"}}},
{"/search/", false, "/search/", nil}, {"/search/", false, "/search/", nil},
{"/search/someth!ng+in+ünìcodé", false, "/search/:query", internal.Params{internal.Param{Key: "query", Value: "someth!ng+in+ünìcodé"}}}, {"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{Key: "query", Value: "someth!ng+in+ünìcodé"}}},
{"/search/someth!ng+in+ünìcodé/", true, "", internal.Params{internal.Param{Key: "query", Value: "someth!ng+in+ünìcodé"}}}, {"/search/someth!ng+in+ünìcodé/", true, "", Params{Param{Key: "query", Value: "someth!ng+in+ünìcodé"}}},
{"/user_gopher", false, "/user_:name", internal.Params{internal.Param{Key: "name", Value: "gopher"}}}, {"/user_gopher", false, "/user_:name", Params{Param{Key: "name", Value: "gopher"}}},
{"/user_gopher/about", false, "/user_:name/about", internal.Params{internal.Param{Key: "name", Value: "gopher"}}}, {"/user_gopher/about", false, "/user_:name/about", Params{Param{Key: "name", Value: "gopher"}}},
{"/files/js/inc/framework.js", false, "/files/:dir/*filepath", internal.Params{internal.Param{Key: "dir", Value: "js"}, internal.Param{Key: "filepath", Value: "/inc/framework.js"}}}, {"/files/js/inc/framework.js", false, "/files/:dir/*filepath", Params{Param{Key: "dir", Value: "js"}, Param{Key: "filepath", Value: "/inc/framework.js"}}},
{"/info/gordon/public", false, "/info/:user/public", internal.Params{internal.Param{Key: "user", Value: "gordon"}}}, {"/info/gordon/public", false, "/info/:user/public", Params{Param{Key: "user", Value: "gordon"}}},
{"/info/gordon/project/go", false, "/info/:user/project/:project", internal.Params{internal.Param{Key: "user", Value: "gordon"}, internal.Param{Key: "project", Value: "go"}}}, {"/info/gordon/project/go", false, "/info/:user/project/:project", Params{Param{Key: "user", Value: "gordon"}, Param{Key: "project", Value: "go"}}},
}) })
checkPriorities(t, tree) checkPriorities(t, tree)
@ -211,18 +209,18 @@ func TestUnescapeParameters(t *testing.T) {
unescape := true unescape := true
checkRequests(t, tree, testRequests{ checkRequests(t, tree, testRequests{
{"/", false, "/", nil}, {"/", false, "/", nil},
{"/cmd/test/", false, "/cmd/:tool/", internal.Params{internal.Param{Key: "tool", Value: "test"}}}, {"/cmd/test/", false, "/cmd/:tool/", Params{Param{Key: "tool", Value: "test"}}},
{"/cmd/test", true, "", internal.Params{internal.Param{Key: "tool", Value: "test"}}}, {"/cmd/test", true, "", Params{Param{Key: "tool", Value: "test"}}},
{"/src/some/file.png", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/some/file.png"}}}, {"/src/some/file.png", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/some/file.png"}}},
{"/src/some/file+test.png", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/some/file test.png"}}}, {"/src/some/file+test.png", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/some/file test.png"}}},
{"/src/some/file++++%%%%test.png", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/some/file++++%%%%test.png"}}}, {"/src/some/file++++%%%%test.png", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/some/file++++%%%%test.png"}}},
{"/src/some/file%2Ftest.png", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/some/file/test.png"}}}, {"/src/some/file%2Ftest.png", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/some/file/test.png"}}},
{"/search/someth!ng+in+ünìcodé", false, "/search/:query", internal.Params{internal.Param{Key: "query", Value: "someth!ng in ünìcodé"}}}, {"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{Key: "query", Value: "someth!ng in ünìcodé"}}},
{"/info/gordon/project/go", false, "/info/:user/project/:project", internal.Params{internal.Param{Key: "user", Value: "gordon"}, internal.Param{Key: "project", Value: "go"}}}, {"/info/gordon/project/go", false, "/info/:user/project/:project", Params{Param{Key: "user", Value: "gordon"}, Param{Key: "project", Value: "go"}}},
{"/info/slash%2Fgordon", false, "/info/:user", internal.Params{internal.Param{Key: "user", Value: "slash/gordon"}}}, {"/info/slash%2Fgordon", false, "/info/:user", Params{Param{Key: "user", Value: "slash/gordon"}}},
{"/info/slash%2Fgordon/project/Project%20%231", false, "/info/:user/project/:project", internal.Params{internal.Param{Key: "user", Value: "slash/gordon"}, internal.Param{Key: "project", Value: "Project #1"}}}, {"/info/slash%2Fgordon/project/Project%20%231", false, "/info/:user/project/:project", Params{Param{Key: "user", Value: "slash/gordon"}, Param{Key: "project", Value: "Project #1"}}},
{"/info/slash%%%%", false, "/info/:user", internal.Params{internal.Param{Key: "user", Value: "slash%%%%"}}}, {"/info/slash%%%%", false, "/info/:user", Params{Param{Key: "user", Value: "slash%%%%"}}},
{"/info/slash%%%%2Fgordon/project/Project%%%%20%231", false, "/info/:user/project/:project", internal.Params{internal.Param{Key: "user", Value: "slash%%%%2Fgordon"}, internal.Param{Key: "project", Value: "Project%%%%20%231"}}}, {"/info/slash%%%%2Fgordon/project/Project%%%%20%231", false, "/info/:user/project/:project", Params{Param{Key: "user", Value: "slash%%%%2Fgordon"}, Param{Key: "project", Value: "Project%%%%20%231"}}},
}, unescape) }, unescape)
checkPriorities(t, tree) checkPriorities(t, tree)
@ -328,9 +326,9 @@ func TestTreeDupliatePath(t *testing.T) {
checkRequests(t, tree, testRequests{ checkRequests(t, tree, testRequests{
{"/", false, "/", nil}, {"/", false, "/", nil},
{"/doc/", false, "/doc/", nil}, {"/doc/", false, "/doc/", nil},
{"/src/some/file.png", false, "/src/*filepath", internal.Params{internal.Param{Key: "filepath", Value: "/some/file.png"}}}, {"/src/some/file.png", false, "/src/*filepath", Params{Param{Key: "filepath", Value: "/some/file.png"}}},
{"/search/someth!ng+in+ünìcodé", false, "/search/:query", internal.Params{internal.Param{Key: "query", Value: "someth!ng+in+ünìcodé"}}}, {"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{Key: "query", Value: "someth!ng+in+ünìcodé"}}},
{"/user_gopher", false, "/user_:name", internal.Params{internal.Param{Key: "name", Value: "gopher"}}}, {"/user_gopher", false, "/user_:name", Params{Param{Key: "name", Value: "gopher"}}},
}) })
} }