mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-24 02:32:17 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
a076bf34f4
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ vendor/*
|
|||||||
!vendor/vendor.json
|
!vendor/vendor.json
|
||||||
coverage.out
|
coverage.out
|
||||||
count.out
|
count.out
|
||||||
|
test
|
||||||
|
4
Makefile
4
Makefile
@ -2,14 +2,14 @@ GOFMT ?= gofmt "-s"
|
|||||||
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||||
GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*")
|
GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*")
|
||||||
|
|
||||||
all: build
|
all: install
|
||||||
|
|
||||||
install: deps
|
install: deps
|
||||||
govendor sync
|
govendor sync
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
go test -v -covermode=count -coverprofile=coverage.out
|
sh coverage.sh
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt:
|
fmt:
|
||||||
|
72
README.md
72
README.md
@ -74,10 +74,10 @@ BenchmarkTigerTonic_GithubAll | 1000 | 1439483 | 239104
|
|||||||
BenchmarkTraffic_GithubAll | 100 | 11383067 | 2659329 | 21848
|
BenchmarkTraffic_GithubAll | 100 | 11383067 | 2659329 | 21848
|
||||||
BenchmarkVulcan_GithubAll | 5000 | 394253 | 19894 | 609
|
BenchmarkVulcan_GithubAll | 5000 | 394253 | 19894 | 609
|
||||||
|
|
||||||
(1): Total Repetitions achieved in constant time, higher means more confident result
|
- (1): Total Repetitions achieved in constant time, higher means more confident result
|
||||||
(2): Single Repetition Duration (ns/op), lower is better
|
- (2): Single Repetition Duration (ns/op), lower is better
|
||||||
(3): Heap Memory (B/op), lower is better
|
- (3): Heap Memory (B/op), lower is better
|
||||||
(4): Average Allocations per Repetition (allocs/op), lower is better
|
- (4): Average Allocations per Repetition (allocs/op), lower is better
|
||||||
|
|
||||||
## Gin v1. stable
|
## Gin v1. stable
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ $ go get github.com/kardianos/govendor
|
|||||||
2. Create your project folder and `cd` inside
|
2. Create your project folder and `cd` inside
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ mkdir -p ~/go/src/github.com/myusername/project && cd "$_"
|
$ mkdir -p $GOPATH/src/github.com/myusername/project && cd "$_"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Vendor init your project and add gin
|
3. Vendor init your project and add gin
|
||||||
@ -385,7 +385,7 @@ func main() {
|
|||||||
r := gin.New()
|
r := gin.New()
|
||||||
|
|
||||||
// Global middleware
|
// Global middleware
|
||||||
// Logger middleware will write the logs to gin.DefaultWriter even you set with GIN_MODE=release.
|
// Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
|
||||||
// By default gin.DefaultWriter = os.Stdout
|
// By default gin.DefaultWriter = os.Stdout
|
||||||
r.Use(gin.Logger())
|
r.Use(gin.Logger())
|
||||||
|
|
||||||
@ -435,7 +435,7 @@ func main() {
|
|||||||
c.String(200, "pong")
|
c.String(200, "pong")
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Run(":8080")
|
router.Run(":8080")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -472,7 +472,7 @@ func main() {
|
|||||||
// Example for binding JSON ({"user": "manu", "password": "123"})
|
// Example for binding JSON ({"user": "manu", "password": "123"})
|
||||||
router.POST("/loginJSON", func(c *gin.Context) {
|
router.POST("/loginJSON", func(c *gin.Context) {
|
||||||
var json Login
|
var json Login
|
||||||
if err = c.ShouldBindJSON(&json); err == nil {
|
if err := c.ShouldBindJSON(&json); err == nil {
|
||||||
if json.User == "manu" && json.Password == "123" {
|
if json.User == "manu" && json.Password == "123" {
|
||||||
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
|
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
|
||||||
} else {
|
} else {
|
||||||
@ -540,7 +540,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
validator "gopkg.in/go-playground/validator.v8"
|
"gopkg.in/go-playground/validator.v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Booking struct {
|
type Booking struct {
|
||||||
@ -1071,7 +1071,7 @@ func main() {
|
|||||||
|
|
||||||
### Goroutines inside a middleware
|
### Goroutines inside a middleware
|
||||||
|
|
||||||
When starting inside a middleware or handler, you **SHOULD NOT** use the original context inside it, you have to use a read-only copy.
|
When starting new Goroutines inside a middleware or handler, you **SHOULD NOT** use the original context inside it, you have to use a read-only copy.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func main() {
|
func main() {
|
||||||
@ -1133,7 +1133,7 @@ func main() {
|
|||||||
|
|
||||||
example for 1-line LetsEncrypt HTTPS servers.
|
example for 1-line LetsEncrypt HTTPS servers.
|
||||||
|
|
||||||
[embedmd]:# (examples/auto-tls/example1.go go)
|
[embedmd]:# (examples/auto-tls/example1/main.go go)
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -1158,7 +1158,7 @@ func main() {
|
|||||||
|
|
||||||
example for custom autocert manager.
|
example for custom autocert manager.
|
||||||
|
|
||||||
[embedmd]:# (examples/auto-tls/example2.go go)
|
[embedmd]:# (examples/auto-tls/example2/main.go go)
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -1190,7 +1190,7 @@ func main() {
|
|||||||
|
|
||||||
### Run multiple service using Gin
|
### Run multiple service using Gin
|
||||||
|
|
||||||
See the [question](https://github.com/gin-gonic/gin/issues/346) and try the folling example:
|
See the [question](https://github.com/gin-gonic/gin/issues/346) and try the following example:
|
||||||
|
|
||||||
[embedmd]:# (examples/multiple-service/main.go go)
|
[embedmd]:# (examples/multiple-service/main.go go)
|
||||||
```go
|
```go
|
||||||
@ -1344,6 +1344,52 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
The `net/http/httptest` package is preferable way for HTTP testing.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
func setupRouter() *gin.Engine {
|
||||||
|
r := gin.Default()
|
||||||
|
r.GET("/ping", func(c *gin.Context) {
|
||||||
|
c.String(200, "pong")
|
||||||
|
})
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := setupRouter()
|
||||||
|
r.Run(":8080")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Test for code example above:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPingRoute(t *testing.T) {
|
||||||
|
router := setupRouter()
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("GET", "/ping", nil)
|
||||||
|
router.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
assert.Equal(t, 200, w.Code)
|
||||||
|
assert.Equal(t, "pong", w.Body.String())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Users [](https://sourcegraph.com/github.com/gin-gonic/gin?badge)
|
## Users [](https://sourcegraph.com/github.com/gin-gonic/gin?badge)
|
||||||
|
|
||||||
Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework.
|
Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framework.
|
||||||
|
12
auth.go
12
auth.go
@ -17,8 +17,8 @@ const AuthUserKey = "user"
|
|||||||
type Accounts map[string]string
|
type Accounts map[string]string
|
||||||
|
|
||||||
type authPair struct {
|
type authPair struct {
|
||||||
Value string
|
value string
|
||||||
User string
|
user string
|
||||||
}
|
}
|
||||||
|
|
||||||
type authPairs []authPair
|
type authPairs []authPair
|
||||||
@ -28,8 +28,8 @@ func (a authPairs) searchCredential(authValue string) (string, bool) {
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
for _, pair := range a {
|
for _, pair := range a {
|
||||||
if pair.Value == authValue {
|
if pair.value == authValue {
|
||||||
return pair.User, true
|
return pair.user, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", false
|
return "", false
|
||||||
@ -74,8 +74,8 @@ func processAccounts(accounts Accounts) authPairs {
|
|||||||
assert1(user != "", "User can not be empty")
|
assert1(user != "", "User can not be empty")
|
||||||
value := authorizationHeader(user, password)
|
value := authorizationHeader(user, password)
|
||||||
pairs = append(pairs, authPair{
|
pairs = append(pairs, authPair{
|
||||||
Value: value,
|
value: value,
|
||||||
User: user,
|
user: user,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return pairs
|
return pairs
|
||||||
|
12
auth_test.go
12
auth_test.go
@ -22,16 +22,16 @@ func TestBasicAuth(t *testing.T) {
|
|||||||
|
|
||||||
assert.Len(t, pairs, 3)
|
assert.Len(t, pairs, 3)
|
||||||
assert.Contains(t, pairs, authPair{
|
assert.Contains(t, pairs, authPair{
|
||||||
User: "bar",
|
user: "bar",
|
||||||
Value: "Basic YmFyOmZvbw==",
|
value: "Basic YmFyOmZvbw==",
|
||||||
})
|
})
|
||||||
assert.Contains(t, pairs, authPair{
|
assert.Contains(t, pairs, authPair{
|
||||||
User: "foo",
|
user: "foo",
|
||||||
Value: "Basic Zm9vOmJhcg==",
|
value: "Basic Zm9vOmJhcg==",
|
||||||
})
|
})
|
||||||
assert.Contains(t, pairs, authPair{
|
assert.Contains(t, pairs, authPair{
|
||||||
User: "admin",
|
user: "admin",
|
||||||
Value: "Basic YWRtaW46cGFzc3dvcmQ=",
|
value: "Basic YWRtaW46cGFzc3dvcmQ=",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +59,6 @@ func BenchmarkOneRouteJSON(B *testing.B) {
|
|||||||
runRequest(B, router, "GET", "/json")
|
runRequest(B, router, "GET", "/json")
|
||||||
}
|
}
|
||||||
|
|
||||||
var htmlContentType = []string{"text/html; charset=utf-8"}
|
|
||||||
|
|
||||||
func BenchmarkOneRouteHTML(B *testing.B) {
|
func BenchmarkOneRouteHTML(B *testing.B) {
|
||||||
router := New()
|
router := New()
|
||||||
t := template.Must(template.New("index").Parse(`
|
t := template.Must(template.New("index").Parse(`
|
||||||
|
@ -7,7 +7,7 @@ package binding
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
validator "gopkg.in/go-playground/validator.v8"
|
"gopkg.in/go-playground/validator.v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -6,9 +6,13 @@ package binding
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin/binding/example"
|
"github.com/gin-gonic/gin/binding/example"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
@ -25,6 +29,116 @@ type FooBarStruct struct {
|
|||||||
Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
|
Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FooStructUseNumber struct {
|
||||||
|
Foo interface{} `json:"foo" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForTimeType struct {
|
||||||
|
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
|
||||||
|
TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForTimeTypeNotFormat struct {
|
||||||
|
TimeFoo time.Time `form:"time_foo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForTimeTypeFailFormat struct {
|
||||||
|
TimeFoo time.Time `form:"time_foo" time_format:"2017-11-15"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForTimeTypeFailLocation struct {
|
||||||
|
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_location:"/asia/chongqing"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForMapType struct {
|
||||||
|
// Unknown type: not support map
|
||||||
|
MapFoo map[string]interface{} `form:"map_foo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvalidNameType struct {
|
||||||
|
TestName string `invalid_name:"test_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvalidNameMapType struct {
|
||||||
|
TestName struct {
|
||||||
|
MapFoo map[string]interface{} `form:"map_foo"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForSliceType struct {
|
||||||
|
SliceFoo []int `form:"slice_foo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForSliceMapType struct {
|
||||||
|
// Unknown type: not support map
|
||||||
|
SliceMapFoo []map[string]interface{} `form:"slice_map_foo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForIntType struct {
|
||||||
|
IntFoo int `form:"int_foo"`
|
||||||
|
IntBar int `form:"int_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForInt8Type struct {
|
||||||
|
Int8Foo int8 `form:"int8_foo"`
|
||||||
|
Int8Bar int8 `form:"int8_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForInt16Type struct {
|
||||||
|
Int16Foo int16 `form:"int16_foo"`
|
||||||
|
Int16Bar int16 `form:"int16_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForInt32Type struct {
|
||||||
|
Int32Foo int32 `form:"int32_foo"`
|
||||||
|
Int32Bar int32 `form:"int32_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForInt64Type struct {
|
||||||
|
Int64Foo int64 `form:"int64_foo"`
|
||||||
|
Int64Bar int64 `form:"int64_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForUintType struct {
|
||||||
|
UintFoo uint `form:"uint_foo"`
|
||||||
|
UintBar uint `form:"uint_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForUint8Type struct {
|
||||||
|
Uint8Foo uint8 `form:"uint8_foo"`
|
||||||
|
Uint8Bar uint8 `form:"uint8_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForUint16Type struct {
|
||||||
|
Uint16Foo uint16 `form:"uint16_foo"`
|
||||||
|
Uint16Bar uint16 `form:"uint16_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForUint32Type struct {
|
||||||
|
Uint32Foo uint32 `form:"uint32_foo"`
|
||||||
|
Uint32Bar uint32 `form:"uint32_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForUint64Type struct {
|
||||||
|
Uint64Foo uint64 `form:"uint64_foo"`
|
||||||
|
Uint64Bar uint64 `form:"uint64_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForBoolType struct {
|
||||||
|
BoolFoo bool `form:"bool_foo"`
|
||||||
|
BoolBar bool `form:"bool_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForFloat32Type struct {
|
||||||
|
Float32Foo float32 `form:"float32_foo"`
|
||||||
|
Float32Bar float32 `form:"float32_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBarStructForFloat64Type struct {
|
||||||
|
Float64Foo float64 `form:"float64_foo"`
|
||||||
|
Float64Bar float64 `form:"float64_bar" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingDefault(t *testing.T) {
|
func TestBindingDefault(t *testing.T) {
|
||||||
assert.Equal(t, Default("GET", ""), Form)
|
assert.Equal(t, Default("GET", ""), Form)
|
||||||
assert.Equal(t, Default("GET", MIMEJSON), Form)
|
assert.Equal(t, Default("GET", MIMEJSON), Form)
|
||||||
@ -55,6 +169,20 @@ func TestBindingJSON(t *testing.T) {
|
|||||||
`{"foo": "bar"}`, `{"bar": "foo"}`)
|
`{"foo": "bar"}`, `{"bar": "foo"}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingJSONUseNumber(t *testing.T) {
|
||||||
|
testBodyBindingUseNumber(t,
|
||||||
|
JSON, "json",
|
||||||
|
"/", "/",
|
||||||
|
`{"foo": 123}`, `{"bar": "foo"}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingJSONUseNumber2(t *testing.T) {
|
||||||
|
testBodyBindingUseNumber2(t,
|
||||||
|
JSON, "json",
|
||||||
|
"/", "/",
|
||||||
|
`{"foo": 123}`, `{"bar": "foo"}`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingForm(t *testing.T) {
|
func TestBindingForm(t *testing.T) {
|
||||||
testFormBinding(t, "POST",
|
testFormBinding(t, "POST",
|
||||||
"/", "/",
|
"/", "/",
|
||||||
@ -67,6 +195,174 @@ func TestBindingForm2(t *testing.T) {
|
|||||||
"", "")
|
"", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingFormForTime(t *testing.T) {
|
||||||
|
testFormBindingForTime(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"time_foo=2017-11-15&time_bar=", "bar2=foo")
|
||||||
|
testFormBindingForTimeNotFormat(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"time_foo=2017-11-15", "bar2=foo")
|
||||||
|
testFormBindingForTimeFailFormat(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"time_foo=2017-11-15", "bar2=foo")
|
||||||
|
testFormBindingForTimeFailLocation(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"time_foo=2017-11-15", "bar2=foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingFormForTime2(t *testing.T) {
|
||||||
|
testFormBindingForTime(t, "GET",
|
||||||
|
"/?time_foo=2017-11-15&time_bar=", "/?bar2=foo",
|
||||||
|
"", "")
|
||||||
|
testFormBindingForTimeNotFormat(t, "GET",
|
||||||
|
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||||
|
"", "")
|
||||||
|
testFormBindingForTimeFailFormat(t, "GET",
|
||||||
|
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||||
|
"", "")
|
||||||
|
testFormBindingForTimeFailLocation(t, "GET",
|
||||||
|
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||||
|
"", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingFormInvalidName(t *testing.T) {
|
||||||
|
testFormBindingInvalidName(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"test_name=bar", "bar2=foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingFormInvalidName2(t *testing.T) {
|
||||||
|
testFormBindingInvalidName2(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"map_foo=bar", "bar2=foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingFormForType(t *testing.T) {
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"map_foo=", "bar2=1", "Map")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"slice_foo=1&slice_foo=2", "bar2=1&bar2=2", "Slice")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?slice_foo=1&slice_foo=2", "/?bar2=1&bar2=2",
|
||||||
|
"", "", "Slice")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"slice_map_foo=1&slice_map_foo=2", "bar2=1&bar2=2", "SliceMap")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2",
|
||||||
|
"", "", "SliceMap")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"int_foo=&int_bar=-12", "bar2=-123", "Int")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?int_foo=&int_bar=-12", "/?bar2=-123",
|
||||||
|
"", "", "Int")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"int8_foo=&int8_bar=-12", "bar2=-123", "Int8")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?int8_foo=&int8_bar=-12", "/?bar2=-123",
|
||||||
|
"", "", "Int8")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"int16_foo=&int16_bar=-12", "bar2=-123", "Int16")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?int16_foo=&int16_bar=-12", "/?bar2=-123",
|
||||||
|
"", "", "Int16")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"int32_foo=&int32_bar=-12", "bar2=-123", "Int32")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?int32_foo=&int32_bar=-12", "/?bar2=-123",
|
||||||
|
"", "", "Int32")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"int64_foo=&int64_bar=-12", "bar2=-123", "Int64")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?int64_foo=&int64_bar=-12", "/?bar2=-123",
|
||||||
|
"", "", "Int64")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"uint_foo=&uint_bar=12", "bar2=123", "Uint")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?uint_foo=&uint_bar=12", "/?bar2=123",
|
||||||
|
"", "", "Uint")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"uint8_foo=&uint8_bar=12", "bar2=123", "Uint8")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?uint8_foo=&uint8_bar=12", "/?bar2=123",
|
||||||
|
"", "", "Uint8")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"uint16_foo=&uint16_bar=12", "bar2=123", "Uint16")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?uint16_foo=&uint16_bar=12", "/?bar2=123",
|
||||||
|
"", "", "Uint16")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"uint32_foo=&uint32_bar=12", "bar2=123", "Uint32")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?uint32_foo=&uint32_bar=12", "/?bar2=123",
|
||||||
|
"", "", "Uint32")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"uint64_foo=&uint64_bar=12", "bar2=123", "Uint64")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?uint64_foo=&uint64_bar=12", "/?bar2=123",
|
||||||
|
"", "", "Uint64")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"bool_foo=&bool_bar=true", "bar2=true", "Bool")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?bool_foo=&bool_bar=true", "/?bar2=true",
|
||||||
|
"", "", "Bool")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"float32_foo=&float32_bar=-12.34", "bar2=12.3", "Float32")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?float32_foo=&float32_bar=-12.34", "/?bar2=12.3",
|
||||||
|
"", "", "Float32")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"float64_foo=&float64_bar=-12.34", "bar2=12.3", "Float64")
|
||||||
|
|
||||||
|
testFormBindingForType(t, "GET",
|
||||||
|
"/?float64_foo=&float64_bar=-12.34", "/?bar2=12.3",
|
||||||
|
"", "", "Float64")
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingQuery(t *testing.T) {
|
func TestBindingQuery(t *testing.T) {
|
||||||
testQueryBinding(t, "POST",
|
testQueryBinding(t, "POST",
|
||||||
"/?foo=bar&bar=foo", "/",
|
"/?foo=bar&bar=foo", "/",
|
||||||
@ -79,6 +375,18 @@ func TestBindingQuery2(t *testing.T) {
|
|||||||
"foo=unused", "")
|
"foo=unused", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingQueryFail(t *testing.T) {
|
||||||
|
testQueryBindingFail(t, "POST",
|
||||||
|
"/?map_foo=", "/",
|
||||||
|
"map_foo=unused", "bar2=foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindingQueryFail2(t *testing.T) {
|
||||||
|
testQueryBindingFail(t, "GET",
|
||||||
|
"/?map_foo=", "/?bar2=foo",
|
||||||
|
"map_foo=unused", "")
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingXML(t *testing.T) {
|
func TestBindingXML(t *testing.T) {
|
||||||
testBodyBinding(t,
|
testBodyBinding(t,
|
||||||
XML, "xml",
|
XML, "xml",
|
||||||
@ -86,12 +394,25 @@ func TestBindingXML(t *testing.T) {
|
|||||||
"<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
|
"<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingXMLFail(t *testing.T) {
|
||||||
|
testBodyBindingFail(t,
|
||||||
|
XML, "xml",
|
||||||
|
"/", "/",
|
||||||
|
"<map><foo>bar<foo></map>", "<map><bar>foo</bar></map>")
|
||||||
|
}
|
||||||
|
|
||||||
func createFormPostRequest() *http.Request {
|
func createFormPostRequest() *http.Request {
|
||||||
req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
|
req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
|
||||||
req.Header.Set("Content-Type", MIMEPOSTForm)
|
req.Header.Set("Content-Type", MIMEPOSTForm)
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createFormPostRequestFail() *http.Request {
|
||||||
|
req, _ := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=bar"))
|
||||||
|
req.Header.Set("Content-Type", MIMEPOSTForm)
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
func createFormMultipartRequest() *http.Request {
|
func createFormMultipartRequest() *http.Request {
|
||||||
boundary := "--testboundary"
|
boundary := "--testboundary"
|
||||||
body := new(bytes.Buffer)
|
body := new(bytes.Buffer)
|
||||||
@ -106,24 +427,53 @@ func createFormMultipartRequest() *http.Request {
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createFormMultipartRequestFail() *http.Request {
|
||||||
|
boundary := "--testboundary"
|
||||||
|
body := new(bytes.Buffer)
|
||||||
|
mw := multipart.NewWriter(body)
|
||||||
|
defer mw.Close()
|
||||||
|
|
||||||
|
mw.SetBoundary(boundary)
|
||||||
|
mw.WriteField("map_foo", "bar")
|
||||||
|
req, _ := http.NewRequest("POST", "/?map_foo=getfoo", body)
|
||||||
|
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingFormPost(t *testing.T) {
|
func TestBindingFormPost(t *testing.T) {
|
||||||
req := createFormPostRequest()
|
req := createFormPostRequest()
|
||||||
var obj FooBarStruct
|
var obj FooBarStruct
|
||||||
FormPost.Bind(req, &obj)
|
FormPost.Bind(req, &obj)
|
||||||
|
|
||||||
|
assert.Equal(t, FormPost.Name(), "form-urlencoded")
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, obj.Foo, "bar")
|
||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, obj.Bar, "foo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingFormPostFail(t *testing.T) {
|
||||||
|
req := createFormPostRequestFail()
|
||||||
|
var obj FooStructForMapType
|
||||||
|
err := FormPost.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingFormMultipart(t *testing.T) {
|
func TestBindingFormMultipart(t *testing.T) {
|
||||||
req := createFormMultipartRequest()
|
req := createFormMultipartRequest()
|
||||||
var obj FooBarStruct
|
var obj FooBarStruct
|
||||||
FormMultipart.Bind(req, &obj)
|
FormMultipart.Bind(req, &obj)
|
||||||
|
|
||||||
|
assert.Equal(t, FormMultipart.Name(), "multipart/form-data")
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, obj.Foo, "bar")
|
||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, obj.Bar, "foo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingFormMultipartFail(t *testing.T) {
|
||||||
|
req := createFormMultipartRequestFail()
|
||||||
|
var obj FooStructForMapType
|
||||||
|
err := FormMultipart.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingProtoBuf(t *testing.T) {
|
func TestBindingProtoBuf(t *testing.T) {
|
||||||
test := &example.Test{
|
test := &example.Test{
|
||||||
Label: proto.String("yes"),
|
Label: proto.String("yes"),
|
||||||
@ -136,6 +486,18 @@ func TestBindingProtoBuf(t *testing.T) {
|
|||||||
string(data), string(data[1:]))
|
string(data), string(data[1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindingProtoBufFail(t *testing.T) {
|
||||||
|
test := &example.Test{
|
||||||
|
Label: proto.String("yes"),
|
||||||
|
}
|
||||||
|
data, _ := proto.Marshal(test)
|
||||||
|
|
||||||
|
testProtoBodyBindingFail(t,
|
||||||
|
ProtoBuf, "protobuf",
|
||||||
|
"/", "/",
|
||||||
|
string(data), string(data[1:]))
|
||||||
|
}
|
||||||
|
|
||||||
func TestBindingMsgPack(t *testing.T) {
|
func TestBindingMsgPack(t *testing.T) {
|
||||||
test := FooStruct{
|
test := FooStruct{
|
||||||
Foo: "bar",
|
Foo: "bar",
|
||||||
@ -216,6 +578,323 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFormBindingFail(t *testing.T) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := FooBarStruct{}
|
||||||
|
req, _ := http.NewRequest("POST", "/", nil)
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFormPostBindingFail(t *testing.T) {
|
||||||
|
b := FormPost
|
||||||
|
assert.Equal(t, b.Name(), "form-urlencoded")
|
||||||
|
|
||||||
|
obj := FooBarStruct{}
|
||||||
|
req, _ := http.NewRequest("POST", "/", nil)
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFormMultipartBindingFail(t *testing.T) {
|
||||||
|
b := FormMultipart
|
||||||
|
assert.Equal(t, b.Name(), "multipart/form-data")
|
||||||
|
|
||||||
|
obj := FooBarStruct{}
|
||||||
|
req, _ := http.NewRequest("POST", "/", nil)
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := FooBarStructForTimeType{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.TimeFoo.Unix(), int64(1510675200))
|
||||||
|
assert.Equal(t, obj.TimeFoo.Location().String(), "Asia/Chongqing")
|
||||||
|
assert.Equal(t, obj.TimeBar.Unix(), int64(-62135596800))
|
||||||
|
assert.Equal(t, obj.TimeBar.Location().String(), "UTC")
|
||||||
|
|
||||||
|
obj = FooBarStructForTimeType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := FooStructForTimeTypeNotFormat{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
obj = FooStructForTimeTypeNotFormat{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := FooStructForTimeTypeFailFormat{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
obj = FooStructForTimeTypeFailFormat{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := FooStructForTimeTypeFailLocation{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
obj = FooStructForTimeTypeFailLocation{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := InvalidNameType{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.TestName, "")
|
||||||
|
|
||||||
|
obj = InvalidNameType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
obj := InvalidNameMapType{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
obj = InvalidNameMapType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody string, typ string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, b.Name(), "form")
|
||||||
|
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
switch typ {
|
||||||
|
case "Int":
|
||||||
|
obj := FooBarStructForIntType{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.IntFoo, int(0))
|
||||||
|
assert.Equal(t, obj.IntBar, int(-12))
|
||||||
|
|
||||||
|
obj = FooBarStructForIntType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Int8":
|
||||||
|
obj := FooBarStructForInt8Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Int8Foo, int8(0))
|
||||||
|
assert.Equal(t, obj.Int8Bar, int8(-12))
|
||||||
|
|
||||||
|
obj = FooBarStructForInt8Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Int16":
|
||||||
|
obj := FooBarStructForInt16Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Int16Foo, int16(0))
|
||||||
|
assert.Equal(t, obj.Int16Bar, int16(-12))
|
||||||
|
|
||||||
|
obj = FooBarStructForInt16Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Int32":
|
||||||
|
obj := FooBarStructForInt32Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Int32Foo, int32(0))
|
||||||
|
assert.Equal(t, obj.Int32Bar, int32(-12))
|
||||||
|
|
||||||
|
obj = FooBarStructForInt32Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Int64":
|
||||||
|
obj := FooBarStructForInt64Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Int64Foo, int64(0))
|
||||||
|
assert.Equal(t, obj.Int64Bar, int64(-12))
|
||||||
|
|
||||||
|
obj = FooBarStructForInt64Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Uint":
|
||||||
|
obj := FooBarStructForUintType{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.UintFoo, uint(0x0))
|
||||||
|
assert.Equal(t, obj.UintBar, uint(0xc))
|
||||||
|
|
||||||
|
obj = FooBarStructForUintType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Uint8":
|
||||||
|
obj := FooBarStructForUint8Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Uint8Foo, uint8(0x0))
|
||||||
|
assert.Equal(t, obj.Uint8Bar, uint8(0xc))
|
||||||
|
|
||||||
|
obj = FooBarStructForUint8Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Uint16":
|
||||||
|
obj := FooBarStructForUint16Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Uint16Foo, uint16(0x0))
|
||||||
|
assert.Equal(t, obj.Uint16Bar, uint16(0xc))
|
||||||
|
|
||||||
|
obj = FooBarStructForUint16Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Uint32":
|
||||||
|
obj := FooBarStructForUint32Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Uint32Foo, uint32(0x0))
|
||||||
|
assert.Equal(t, obj.Uint32Bar, uint32(0xc))
|
||||||
|
|
||||||
|
obj = FooBarStructForUint32Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Uint64":
|
||||||
|
obj := FooBarStructForUint64Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Uint64Foo, uint64(0x0))
|
||||||
|
assert.Equal(t, obj.Uint64Bar, uint64(0xc))
|
||||||
|
|
||||||
|
obj = FooBarStructForUint64Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Float32":
|
||||||
|
obj := FooBarStructForFloat32Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Float32Foo, float32(0.0))
|
||||||
|
assert.Equal(t, obj.Float32Bar, float32(-12.34))
|
||||||
|
|
||||||
|
obj = FooBarStructForFloat32Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Float64":
|
||||||
|
obj := FooBarStructForFloat64Type{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.Float64Foo, float64(0.0))
|
||||||
|
assert.Equal(t, obj.Float64Bar, float64(-12.34))
|
||||||
|
|
||||||
|
obj = FooBarStructForFloat64Type{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Bool":
|
||||||
|
obj := FooBarStructForBoolType{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.BoolFoo, false)
|
||||||
|
assert.Equal(t, obj.BoolBar, true)
|
||||||
|
|
||||||
|
obj = FooBarStructForBoolType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Slice":
|
||||||
|
obj := FooStructForSliceType{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, obj.SliceFoo, []int{1, 2})
|
||||||
|
|
||||||
|
obj = FooStructForSliceType{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "Map":
|
||||||
|
obj := FooStructForMapType{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
case "SliceMap":
|
||||||
|
obj := FooStructForSliceMapType{}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) {
|
func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
b := Query
|
b := Query
|
||||||
assert.Equal(t, b.Name(), "query")
|
assert.Equal(t, b.Name(), "query")
|
||||||
@ -231,6 +910,19 @@ func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string)
|
|||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, obj.Bar, "foo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Query
|
||||||
|
assert.Equal(t, b.Name(), "query")
|
||||||
|
|
||||||
|
obj := FooStructForMapType{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
assert.Equal(t, b.Name(), name)
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
@ -246,6 +938,58 @@ func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
|
obj := FooStructUseNumber{}
|
||||||
|
req := requestWithBody("POST", path, body)
|
||||||
|
EnableDecoderUseNumber = true
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// we hope it is int64(123)
|
||||||
|
v, e := obj.Foo.(json.Number).Int64()
|
||||||
|
assert.NoError(t, e)
|
||||||
|
assert.Equal(t, v, int64(123))
|
||||||
|
|
||||||
|
obj = FooStructUseNumber{}
|
||||||
|
req = requestWithBody("POST", badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
|
obj := FooStructUseNumber{}
|
||||||
|
req := requestWithBody("POST", path, body)
|
||||||
|
EnableDecoderUseNumber = false
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// it will return float64(123) if not use EnableDecoderUseNumber
|
||||||
|
// maybe it is not hoped
|
||||||
|
assert.Equal(t, obj.Foo, float64(123))
|
||||||
|
|
||||||
|
obj = FooStructUseNumber{}
|
||||||
|
req = requestWithBody("POST", badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
|
obj := FooStruct{}
|
||||||
|
req := requestWithBody("POST", path, body)
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, obj.Foo, "")
|
||||||
|
|
||||||
|
obj = FooStruct{}
|
||||||
|
req = requestWithBody("POST", badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
assert.Equal(t, b.Name(), name)
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
@ -263,6 +1007,30 @@ func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, ba
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type hook struct{}
|
||||||
|
|
||||||
|
func (h hook) Read([]byte) (int, error) {
|
||||||
|
return 0, errors.New("error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
|
obj := example.Test{}
|
||||||
|
req := requestWithBody("POST", path, body)
|
||||||
|
|
||||||
|
req.Body = ioutil.NopCloser(&hook{})
|
||||||
|
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
obj = example.Test{}
|
||||||
|
req = requestWithBody("POST", badPath, badBody)
|
||||||
|
req.Header.Add("Content-Type", MIMEPROTOBUF)
|
||||||
|
err = ProtoBuf.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
|
||||||
assert.Equal(t, b.Name(), name)
|
assert.Equal(t, b.Name(), name)
|
||||||
|
|
||||||
|
@ -179,12 +179,3 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
|
|||||||
value.Set(reflect.ValueOf(t))
|
value.Set(reflect.ValueOf(t))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't pass in pointers to bind to. Can lead to bugs. See:
|
|
||||||
// https://github.com/codegangsta/martini-contrib/issues/40
|
|
||||||
// https://github.com/codegangsta/martini-contrib/pull/34#issuecomment-29683659
|
|
||||||
func ensureNotPointer(obj interface{}) {
|
|
||||||
if reflect.TypeOf(obj).Kind() == reflect.Ptr {
|
|
||||||
panic("Pointers are not accepted as binding models")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -10,9 +10,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin/json"
|
"github.com/gin-gonic/gin/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var EnableDecoderUseNumber = false
|
||||||
EnableDecoderUseNumber = false
|
|
||||||
)
|
|
||||||
|
|
||||||
type jsonBinding struct{}
|
type jsonBinding struct{}
|
||||||
|
|
||||||
|
@ -4,9 +4,7 @@
|
|||||||
|
|
||||||
package binding
|
package binding
|
||||||
|
|
||||||
import (
|
import "net/http"
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
type queryBinding struct{}
|
type queryBinding struct{}
|
||||||
|
|
||||||
|
@ -10,9 +10,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
validator "gopkg.in/go-playground/validator.v8"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/go-playground/validator.v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testInterface interface {
|
type testInterface interface {
|
||||||
|
17
context.go
17
context.go
@ -33,9 +33,7 @@ const (
|
|||||||
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
|
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const abortIndex int8 = math.MaxInt8 / 2
|
||||||
abortIndex int8 = math.MaxInt8 / 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
// Context is the most important part of gin. It allows us to pass variables between middleware,
|
||||||
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
// manage the flow, validate the JSON of a request and render a JSON response for example.
|
||||||
@ -105,8 +103,7 @@ func (c *Context) Handler() HandlerFunc {
|
|||||||
// See example in GitHub.
|
// See example in GitHub.
|
||||||
func (c *Context) Next() {
|
func (c *Context) Next() {
|
||||||
c.index++
|
c.index++
|
||||||
s := int8(len(c.handlers))
|
for s := int8(len(c.handlers)); c.index < s; c.index++ {
|
||||||
for ; c.index < s; c.index++ {
|
|
||||||
c.handlers[c.index](c)
|
c.handlers[c.index](c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,10 +449,10 @@ func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error
|
|||||||
// Depending the "Content-Type" header different bindings are used:
|
// Depending the "Content-Type" header different bindings are used:
|
||||||
// "application/json" --> JSON binding
|
// "application/json" --> JSON binding
|
||||||
// "application/xml" --> XML binding
|
// "application/xml" --> XML binding
|
||||||
// otherwise --> returns an error
|
// otherwise --> returns an error.
|
||||||
// It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input.
|
// It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input.
|
||||||
// It decodes the json payload into the struct specified as a pointer.
|
// It decodes the json payload into the struct specified as a pointer.
|
||||||
// It will writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid.
|
// It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid.
|
||||||
func (c *Context) Bind(obj interface{}) error {
|
func (c *Context) Bind(obj interface{}) error {
|
||||||
b := binding.Default(c.Request.Method, c.ContentType())
|
b := binding.Default(c.Request.Method, c.ContentType())
|
||||||
return c.MustBindWith(obj, b)
|
return c.MustBindWith(obj, b)
|
||||||
@ -521,11 +518,11 @@ func (c *Context) ClientIP() string {
|
|||||||
clientIP = clientIP[0:index]
|
clientIP = clientIP[0:index]
|
||||||
}
|
}
|
||||||
clientIP = strings.TrimSpace(clientIP)
|
clientIP = strings.TrimSpace(clientIP)
|
||||||
if len(clientIP) > 0 {
|
if clientIP != "" {
|
||||||
return clientIP
|
return clientIP
|
||||||
}
|
}
|
||||||
clientIP = strings.TrimSpace(c.requestHeader("X-Real-Ip"))
|
clientIP = strings.TrimSpace(c.requestHeader("X-Real-Ip"))
|
||||||
if len(clientIP) > 0 {
|
if clientIP != "" {
|
||||||
return clientIP
|
return clientIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,7 +585,7 @@ func (c *Context) Status(code int) {
|
|||||||
// It writes a header in the response.
|
// It writes a header in the response.
|
||||||
// If value == "", this method removes the header `c.Writer.Header().Del(key)`
|
// If value == "", this method removes the header `c.Writer.Header().Del(key)`
|
||||||
func (c *Context) Header(key, value string) {
|
func (c *Context) Header(key, value string) {
|
||||||
if len(value) == 0 {
|
if value == "" {
|
||||||
c.Writer.Header().Del(key)
|
c.Writer.Header().Del(key)
|
||||||
} else {
|
} else {
|
||||||
c.Writer.Header().Set(key, value)
|
c.Writer.Header().Set(key, value)
|
||||||
|
311
context_test.go
311
context_test.go
@ -180,14 +180,14 @@ func TestContextSetGet(t *testing.T) {
|
|||||||
c.Set("foo", "bar")
|
c.Set("foo", "bar")
|
||||||
|
|
||||||
value, err := c.Get("foo")
|
value, err := c.Get("foo")
|
||||||
assert.Equal(t, value, "bar")
|
assert.Equal(t, "bar", value)
|
||||||
assert.True(t, err)
|
assert.True(t, err)
|
||||||
|
|
||||||
value, err = c.Get("foo2")
|
value, err = c.Get("foo2")
|
||||||
assert.Nil(t, value)
|
assert.Nil(t, value)
|
||||||
assert.False(t, err)
|
assert.False(t, err)
|
||||||
|
|
||||||
assert.Equal(t, c.MustGet("foo"), "bar")
|
assert.Equal(t, "bar", c.MustGet("foo"))
|
||||||
assert.Panics(t, func() { c.MustGet("no_exist") })
|
assert.Panics(t, func() { c.MustGet("no_exist") })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ func TestContextGetString(t *testing.T) {
|
|||||||
func TestContextSetGetBool(t *testing.T) {
|
func TestContextSetGetBool(t *testing.T) {
|
||||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||||
c.Set("bool", true)
|
c.Set("bool", true)
|
||||||
assert.Equal(t, true, c.GetBool("bool"))
|
assert.True(t, c.GetBool("bool"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextGetInt(t *testing.T) {
|
func TestContextGetInt(t *testing.T) {
|
||||||
@ -342,26 +342,26 @@ func TestContextQuery(t *testing.T) {
|
|||||||
|
|
||||||
value, ok := c.GetQuery("foo")
|
value, ok := c.GetQuery("foo")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, value, "bar")
|
assert.Equal(t, "bar", value)
|
||||||
assert.Equal(t, c.DefaultQuery("foo", "none"), "bar")
|
assert.Equal(t, "bar", c.DefaultQuery("foo", "none"))
|
||||||
assert.Equal(t, c.Query("foo"), "bar")
|
assert.Equal(t, "bar", c.Query("foo"))
|
||||||
|
|
||||||
value, ok = c.GetQuery("page")
|
value, ok = c.GetQuery("page")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, value, "10")
|
assert.Equal(t, "10", value)
|
||||||
assert.Equal(t, c.DefaultQuery("page", "0"), "10")
|
assert.Equal(t, "10", c.DefaultQuery("page", "0"))
|
||||||
assert.Equal(t, c.Query("page"), "10")
|
assert.Equal(t, "10", c.Query("page"))
|
||||||
|
|
||||||
value, ok = c.GetQuery("id")
|
value, ok = c.GetQuery("id")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Empty(t, value)
|
assert.Empty(t, value)
|
||||||
assert.Equal(t, c.DefaultQuery("id", "nada"), "")
|
assert.Empty(t, c.DefaultQuery("id", "nada"))
|
||||||
assert.Empty(t, c.Query("id"))
|
assert.Empty(t, c.Query("id"))
|
||||||
|
|
||||||
value, ok = c.GetQuery("NoKey")
|
value, ok = c.GetQuery("NoKey")
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
assert.Empty(t, value)
|
assert.Empty(t, value)
|
||||||
assert.Equal(t, c.DefaultQuery("NoKey", "nada"), "nada")
|
assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
|
||||||
assert.Empty(t, c.Query("NoKey"))
|
assert.Empty(t, c.Query("NoKey"))
|
||||||
|
|
||||||
// postform should not mess
|
// postform should not mess
|
||||||
@ -377,29 +377,29 @@ func TestContextQueryAndPostForm(t *testing.T) {
|
|||||||
c.Request, _ = http.NewRequest("POST", "/?both=GET&id=main&id=omit&array[]=first&array[]=second", body)
|
c.Request, _ = http.NewRequest("POST", "/?both=GET&id=main&id=omit&array[]=first&array[]=second", body)
|
||||||
c.Request.Header.Add("Content-Type", MIMEPOSTForm)
|
c.Request.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
|
||||||
assert.Equal(t, c.DefaultPostForm("foo", "none"), "bar")
|
assert.Equal(t, "bar", c.DefaultPostForm("foo", "none"))
|
||||||
assert.Equal(t, c.PostForm("foo"), "bar")
|
assert.Equal(t, "bar", c.PostForm("foo"))
|
||||||
assert.Empty(t, c.Query("foo"))
|
assert.Empty(t, c.Query("foo"))
|
||||||
|
|
||||||
value, ok := c.GetPostForm("page")
|
value, ok := c.GetPostForm("page")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, value, "11")
|
assert.Equal(t, "11", value)
|
||||||
assert.Equal(t, c.DefaultPostForm("page", "0"), "11")
|
assert.Equal(t, "11", c.DefaultPostForm("page", "0"))
|
||||||
assert.Equal(t, c.PostForm("page"), "11")
|
assert.Equal(t, "11", c.PostForm("page"))
|
||||||
assert.Equal(t, c.Query("page"), "")
|
assert.Empty(t, c.Query("page"))
|
||||||
|
|
||||||
value, ok = c.GetPostForm("both")
|
value, ok = c.GetPostForm("both")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Empty(t, value)
|
assert.Empty(t, value)
|
||||||
assert.Empty(t, c.PostForm("both"))
|
assert.Empty(t, c.PostForm("both"))
|
||||||
assert.Equal(t, c.DefaultPostForm("both", "nothing"), "")
|
assert.Empty(t, c.DefaultPostForm("both", "nothing"))
|
||||||
assert.Equal(t, c.Query("both"), "GET")
|
assert.Equal(t, "GET", c.Query("both"), "GET")
|
||||||
|
|
||||||
value, ok = c.GetQuery("id")
|
value, ok = c.GetQuery("id")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, value, "main")
|
assert.Equal(t, "main", value)
|
||||||
assert.Equal(t, c.DefaultPostForm("id", "000"), "000")
|
assert.Equal(t, "000", c.DefaultPostForm("id", "000"))
|
||||||
assert.Equal(t, c.Query("id"), "main")
|
assert.Equal(t, "main", c.Query("id"))
|
||||||
assert.Empty(t, c.PostForm("id"))
|
assert.Empty(t, c.PostForm("id"))
|
||||||
|
|
||||||
value, ok = c.GetQuery("NoKey")
|
value, ok = c.GetQuery("NoKey")
|
||||||
@ -408,8 +408,8 @@ func TestContextQueryAndPostForm(t *testing.T) {
|
|||||||
value, ok = c.GetPostForm("NoKey")
|
value, ok = c.GetPostForm("NoKey")
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
assert.Empty(t, value)
|
assert.Empty(t, value)
|
||||||
assert.Equal(t, c.DefaultPostForm("NoKey", "nada"), "nada")
|
assert.Equal(t, "nada", c.DefaultPostForm("NoKey", "nada"))
|
||||||
assert.Equal(t, c.DefaultQuery("NoKey", "nothing"), "nothing")
|
assert.Equal(t, "nothing", c.DefaultQuery("NoKey", "nothing"))
|
||||||
assert.Empty(t, c.PostForm("NoKey"))
|
assert.Empty(t, c.PostForm("NoKey"))
|
||||||
assert.Empty(t, c.Query("NoKey"))
|
assert.Empty(t, c.Query("NoKey"))
|
||||||
|
|
||||||
@ -421,11 +421,11 @@ func TestContextQueryAndPostForm(t *testing.T) {
|
|||||||
Array []string `form:"array[]"`
|
Array []string `form:"array[]"`
|
||||||
}
|
}
|
||||||
assert.NoError(t, c.Bind(&obj))
|
assert.NoError(t, c.Bind(&obj))
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, "bar", obj.Foo, "bar")
|
||||||
assert.Equal(t, obj.ID, "main")
|
assert.Equal(t, "main", obj.ID, "main")
|
||||||
assert.Equal(t, obj.Page, 11)
|
assert.Equal(t, 11, obj.Page, 11)
|
||||||
assert.Equal(t, obj.Both, "")
|
assert.Empty(t, obj.Both)
|
||||||
assert.Equal(t, obj.Array, []string{"first", "second"})
|
assert.Equal(t, []string{"first", "second"}, obj.Array)
|
||||||
|
|
||||||
values, ok := c.GetQueryArray("array[]")
|
values, ok := c.GetQueryArray("array[]")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
@ -460,37 +460,37 @@ func TestContextPostFormMultipart(t *testing.T) {
|
|||||||
BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
|
BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
|
||||||
}
|
}
|
||||||
assert.NoError(t, c.Bind(&obj))
|
assert.NoError(t, c.Bind(&obj))
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, "bar", obj.Foo)
|
||||||
assert.Equal(t, obj.Bar, "10")
|
assert.Equal(t, "10", obj.Bar)
|
||||||
assert.Equal(t, obj.BarAsInt, 10)
|
assert.Equal(t, 10, obj.BarAsInt)
|
||||||
assert.Equal(t, obj.Array, []string{"first", "second"})
|
assert.Equal(t, []string{"first", "second"}, obj.Array)
|
||||||
assert.Equal(t, obj.ID, "")
|
assert.Empty(t, obj.ID)
|
||||||
assert.Equal(t, obj.TimeLocal.Format("02/01/2006 15:04"), "31/12/2016 14:55")
|
assert.Equal(t, "31/12/2016 14:55", obj.TimeLocal.Format("02/01/2006 15:04"))
|
||||||
assert.Equal(t, obj.TimeLocal.Location(), time.Local)
|
assert.Equal(t, time.Local, obj.TimeLocal.Location())
|
||||||
assert.Equal(t, obj.TimeUTC.Format("02/01/2006 15:04"), "31/12/2016 14:55")
|
assert.Equal(t, "31/12/2016 14:55", obj.TimeUTC.Format("02/01/2006 15:04"))
|
||||||
assert.Equal(t, obj.TimeUTC.Location(), time.UTC)
|
assert.Equal(t, time.UTC, obj.TimeUTC.Location())
|
||||||
loc, _ := time.LoadLocation("Asia/Tokyo")
|
loc, _ := time.LoadLocation("Asia/Tokyo")
|
||||||
assert.Equal(t, obj.TimeLocation.Format("02/01/2006 15:04"), "31/12/2016 14:55")
|
assert.Equal(t, "31/12/2016 14:55", obj.TimeLocation.Format("02/01/2006 15:04"))
|
||||||
assert.Equal(t, obj.TimeLocation.Location(), loc)
|
assert.Equal(t, loc, obj.TimeLocation.Location())
|
||||||
assert.True(t, obj.BlankTime.IsZero())
|
assert.True(t, obj.BlankTime.IsZero())
|
||||||
|
|
||||||
value, ok := c.GetQuery("foo")
|
value, ok := c.GetQuery("foo")
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
assert.Empty(t, value)
|
assert.Empty(t, value)
|
||||||
assert.Empty(t, c.Query("bar"))
|
assert.Empty(t, c.Query("bar"))
|
||||||
assert.Equal(t, c.DefaultQuery("id", "nothing"), "nothing")
|
assert.Equal(t, "nothing", c.DefaultQuery("id", "nothing"))
|
||||||
|
|
||||||
value, ok = c.GetPostForm("foo")
|
value, ok = c.GetPostForm("foo")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, value, "bar")
|
assert.Equal(t, "bar", value)
|
||||||
assert.Equal(t, c.PostForm("foo"), "bar")
|
assert.Equal(t, "bar", c.PostForm("foo"))
|
||||||
|
|
||||||
value, ok = c.GetPostForm("array")
|
value, ok = c.GetPostForm("array")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, value, "first")
|
assert.Equal(t, "first", value)
|
||||||
assert.Equal(t, c.PostForm("array"), "first")
|
assert.Equal(t, "first", c.PostForm("array"))
|
||||||
|
|
||||||
assert.Equal(t, c.DefaultPostForm("bar", "nothing"), "10")
|
assert.Equal(t, "10", c.DefaultPostForm("bar", "nothing"))
|
||||||
|
|
||||||
value, ok = c.GetPostForm("id")
|
value, ok = c.GetPostForm("id")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
@ -501,7 +501,7 @@ func TestContextPostFormMultipart(t *testing.T) {
|
|||||||
value, ok = c.GetPostForm("nokey")
|
value, ok = c.GetPostForm("nokey")
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
assert.Empty(t, value)
|
assert.Empty(t, value)
|
||||||
assert.Equal(t, c.DefaultPostForm("nokey", "nothing"), "nothing")
|
assert.Equal(t, "nothing", c.DefaultPostForm("nokey", "nothing"))
|
||||||
|
|
||||||
values, ok := c.GetPostFormArray("array")
|
values, ok := c.GetPostFormArray("array")
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
@ -523,13 +523,13 @@ func TestContextPostFormMultipart(t *testing.T) {
|
|||||||
func TestContextSetCookie(t *testing.T) {
|
func TestContextSetCookie(t *testing.T) {
|
||||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||||
c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
|
c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
|
||||||
assert.Equal(t, c.Writer.Header().Get("Set-Cookie"), "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure")
|
assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextSetCookiePathEmpty(t *testing.T) {
|
func TestContextSetCookiePathEmpty(t *testing.T) {
|
||||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||||
c.SetCookie("user", "gin", 1, "", "localhost", true, true)
|
c.SetCookie("user", "gin", 1, "", "localhost", true, true)
|
||||||
assert.Equal(t, c.Writer.Header().Get("Set-Cookie"), "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure")
|
assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextGetCookie(t *testing.T) {
|
func TestContextGetCookie(t *testing.T) {
|
||||||
@ -537,17 +537,17 @@ func TestContextGetCookie(t *testing.T) {
|
|||||||
c.Request, _ = http.NewRequest("GET", "/get", nil)
|
c.Request, _ = http.NewRequest("GET", "/get", nil)
|
||||||
c.Request.Header.Set("Cookie", "user=gin")
|
c.Request.Header.Set("Cookie", "user=gin")
|
||||||
cookie, _ := c.Cookie("user")
|
cookie, _ := c.Cookie("user")
|
||||||
assert.Equal(t, cookie, "gin")
|
assert.Equal(t, "gin", cookie)
|
||||||
|
|
||||||
_, err := c.Cookie("nokey")
|
_, err := c.Cookie("nokey")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextBodyAllowedForStatus(t *testing.T) {
|
func TestContextBodyAllowedForStatus(t *testing.T) {
|
||||||
assert.Equal(t, false, bodyAllowedForStatus(102))
|
assert.False(t, false, bodyAllowedForStatus(102))
|
||||||
assert.Equal(t, false, bodyAllowedForStatus(204))
|
assert.False(t, false, bodyAllowedForStatus(204))
|
||||||
assert.Equal(t, false, bodyAllowedForStatus(304))
|
assert.False(t, false, bodyAllowedForStatus(304))
|
||||||
assert.Equal(t, true, bodyAllowedForStatus(500))
|
assert.True(t, true, bodyAllowedForStatus(500))
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestPanicRender struct {
|
type TestPanicRender struct {
|
||||||
@ -593,7 +593,7 @@ func TestContextRenderNoContentJSON(t *testing.T) {
|
|||||||
c.JSON(204, H{"foo": "bar"})
|
c.JSON(204, H{"foo": "bar"})
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +620,7 @@ func TestContextRenderNoContentAPIJSON(t *testing.T) {
|
|||||||
c.JSON(204, H{"foo": "bar"})
|
c.JSON(204, H{"foo": "bar"})
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/vnd.api+json")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/vnd.api+json")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +632,7 @@ func TestContextRenderIndentedJSON(t *testing.T) {
|
|||||||
|
|
||||||
c.IndentedJSON(201, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
|
c.IndentedJSON(201, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}", w.Body.String())
|
assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}", w.Body.String())
|
||||||
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
@ -645,7 +645,7 @@ func TestContextRenderNoContentIndentedJSON(t *testing.T) {
|
|||||||
c.IndentedJSON(204, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
|
c.IndentedJSON(204, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,9 +658,9 @@ func TestContextRenderSecureJSON(t *testing.T) {
|
|||||||
router.SecureJsonPrefix("&&&START&&&")
|
router.SecureJsonPrefix("&&&START&&&")
|
||||||
c.SecureJSON(201, []string{"foo", "bar"})
|
c.SecureJSON(201, []string{"foo", "bar"})
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "&&&START&&&[\"foo\",\"bar\"]")
|
assert.Equal(t, "&&&START&&&[\"foo\",\"bar\"]", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that no Custom JSON is rendered if code is 204
|
// Tests that no Custom JSON is rendered if code is 204
|
||||||
@ -671,8 +671,8 @@ func TestContextRenderNoContentSecureJSON(t *testing.T) {
|
|||||||
c.SecureJSON(204, []string{"foo", "bar"})
|
c.SecureJSON(204, []string{"foo", "bar"})
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the response executes the templates
|
// Tests that the response executes the templates
|
||||||
@ -680,14 +680,39 @@ func TestContextRenderNoContentSecureJSON(t *testing.T) {
|
|||||||
func TestContextRenderHTML(t *testing.T) {
|
func TestContextRenderHTML(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
c, router := CreateTestContext(w)
|
c, router := CreateTestContext(w)
|
||||||
|
|
||||||
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
||||||
router.SetHTMLTemplate(templ)
|
router.SetHTMLTemplate(templ)
|
||||||
|
|
||||||
c.HTML(201, "t", H{"name": "alexandernyquist"})
|
c.HTML(201, "t", H{"name": "alexandernyquist"})
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "Hello alexandernyquist")
|
assert.Equal(t, "Hello alexandernyquist", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContextRenderHTML2(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, router := CreateTestContext(w)
|
||||||
|
|
||||||
|
// print debug warning log when Engine.trees > 0
|
||||||
|
router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
|
||||||
|
assert.Len(t, router.trees, 1)
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
setup(&b)
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
||||||
|
router.SetHTMLTemplate(templ)
|
||||||
|
|
||||||
|
assert.Equal(t, "[GIN-debug] [WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called\nat initialization. ie. before any route is registered or the router is listening in a socket:\n\n\trouter := gin.Default()\n\trouter.SetHTMLTemplate(template) // << good place\n\n", b.String())
|
||||||
|
|
||||||
|
c.HTML(201, "t", H{"name": "alexandernyquist"})
|
||||||
|
|
||||||
|
assert.Equal(t, 201, w.Code)
|
||||||
|
assert.Equal(t, "Hello alexandernyquist", w.Body.String())
|
||||||
|
assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that no HTML is rendered if code is 204
|
// Tests that no HTML is rendered if code is 204
|
||||||
@ -700,8 +725,8 @@ func TestContextRenderNoContentHTML(t *testing.T) {
|
|||||||
c.HTML(204, "t", H{"name": "alexandernyquist"})
|
c.HTML(204, "t", H{"name": "alexandernyquist"})
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestContextXML tests that the response is serialized as XML
|
// TestContextXML tests that the response is serialized as XML
|
||||||
@ -712,9 +737,9 @@ func TestContextRenderXML(t *testing.T) {
|
|||||||
|
|
||||||
c.XML(201, H{"foo": "bar"})
|
c.XML(201, H{"foo": "bar"})
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "<map><foo>bar</foo></map>")
|
assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
|
assert.Equal(t, "application/xml; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that no XML is rendered if code is 204
|
// Tests that no XML is rendered if code is 204
|
||||||
@ -725,8 +750,8 @@ func TestContextRenderNoContentXML(t *testing.T) {
|
|||||||
c.XML(204, H{"foo": "bar"})
|
c.XML(204, H{"foo": "bar"})
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
|
assert.Equal(t, "application/xml; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestContextString tests that the response is returned
|
// TestContextString tests that the response is returned
|
||||||
@ -737,9 +762,9 @@ func TestContextRenderString(t *testing.T) {
|
|||||||
|
|
||||||
c.String(201, "test %s %d", "string", 2)
|
c.String(201, "test %s %d", "string", 2)
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "test string 2")
|
assert.Equal(t, "test string 2", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, "text/plain; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that no String is rendered if code is 204
|
// Tests that no String is rendered if code is 204
|
||||||
@ -750,8 +775,8 @@ func TestContextRenderNoContentString(t *testing.T) {
|
|||||||
c.String(204, "test %s %d", "string", 2)
|
c.String(204, "test %s %d", "string", 2)
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, "text/plain; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestContextString tests that the response is returned
|
// TestContextString tests that the response is returned
|
||||||
@ -763,9 +788,9 @@ func TestContextRenderHTMLString(t *testing.T) {
|
|||||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||||
c.String(201, "<html>%s %d</html>", "string", 3)
|
c.String(201, "<html>%s %d</html>", "string", 3)
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "<html>string 3</html>")
|
assert.Equal(t, "<html>string 3</html>", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that no HTML String is rendered if code is 204
|
// Tests that no HTML String is rendered if code is 204
|
||||||
@ -777,8 +802,8 @@ func TestContextRenderNoContentHTMLString(t *testing.T) {
|
|||||||
c.String(204, "<html>%s %d</html>", "string", 3)
|
c.String(204, "<html>%s %d</html>", "string", 3)
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestContextData tests that the response can be written from `bytesting`
|
// TestContextData tests that the response can be written from `bytesting`
|
||||||
@ -789,9 +814,9 @@ func TestContextRenderData(t *testing.T) {
|
|||||||
|
|
||||||
c.Data(201, "text/csv", []byte(`foo,bar`))
|
c.Data(201, "text/csv", []byte(`foo,bar`))
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "foo,bar")
|
assert.Equal(t, "foo,bar", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/csv")
|
assert.Equal(t, "text/csv", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that no Custom Data is rendered if code is 204
|
// Tests that no Custom Data is rendered if code is 204
|
||||||
@ -802,8 +827,8 @@ func TestContextRenderNoContentData(t *testing.T) {
|
|||||||
c.Data(204, "text/csv", []byte(`foo,bar`))
|
c.Data(204, "text/csv", []byte(`foo,bar`))
|
||||||
|
|
||||||
assert.Equal(t, 204, w.Code)
|
assert.Equal(t, 204, w.Code)
|
||||||
assert.Equal(t, "", w.Body.String())
|
assert.Empty(t, w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/csv")
|
assert.Equal(t, "text/csv", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextRenderSSE(t *testing.T) {
|
func TestContextRenderSSE(t *testing.T) {
|
||||||
@ -830,9 +855,9 @@ func TestContextRenderFile(t *testing.T) {
|
|||||||
c.Request, _ = http.NewRequest("GET", "/", nil)
|
c.Request, _ = http.NewRequest("GET", "/", nil)
|
||||||
c.File("./gin.go")
|
c.File("./gin.go")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
assert.Contains(t, w.Body.String(), "func New() *Engine {")
|
assert.Contains(t, w.Body.String(), "func New() *Engine {")
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, "text/plain; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestContextRenderYAML tests that the response is serialized as YAML
|
// TestContextRenderYAML tests that the response is serialized as YAML
|
||||||
@ -843,9 +868,9 @@ func TestContextRenderYAML(t *testing.T) {
|
|||||||
|
|
||||||
c.YAML(201, H{"foo": "bar"})
|
c.YAML(201, H{"foo": "bar"})
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "foo: bar\n")
|
assert.Equal(t, "foo: bar\n", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/x-yaml; charset=utf-8")
|
assert.Equal(t, "application/x-yaml; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextHeaders(t *testing.T) {
|
func TestContextHeaders(t *testing.T) {
|
||||||
@ -853,13 +878,13 @@ func TestContextHeaders(t *testing.T) {
|
|||||||
c.Header("Content-Type", "text/plain")
|
c.Header("Content-Type", "text/plain")
|
||||||
c.Header("X-Custom", "value")
|
c.Header("X-Custom", "value")
|
||||||
|
|
||||||
assert.Equal(t, c.Writer.Header().Get("Content-Type"), "text/plain")
|
assert.Equal(t, "text/plain", c.Writer.Header().Get("Content-Type"))
|
||||||
assert.Equal(t, c.Writer.Header().Get("X-Custom"), "value")
|
assert.Equal(t, "value", c.Writer.Header().Get("X-Custom"))
|
||||||
|
|
||||||
c.Header("Content-Type", "text/html")
|
c.Header("Content-Type", "text/html")
|
||||||
c.Header("X-Custom", "")
|
c.Header("X-Custom", "")
|
||||||
|
|
||||||
assert.Equal(t, c.Writer.Header().Get("Content-Type"), "text/html")
|
assert.Equal(t, "text/html", c.Writer.Header().Get("Content-Type"))
|
||||||
_, exist := c.Writer.Header()["X-Custom"]
|
_, exist := c.Writer.Header()["X-Custom"]
|
||||||
assert.False(t, exist)
|
assert.False(t, exist)
|
||||||
}
|
}
|
||||||
@ -875,8 +900,8 @@ func TestContextRenderRedirectWithRelativePath(t *testing.T) {
|
|||||||
|
|
||||||
c.Redirect(301, "/path")
|
c.Redirect(301, "/path")
|
||||||
c.Writer.WriteHeaderNow()
|
c.Writer.WriteHeaderNow()
|
||||||
assert.Equal(t, w.Code, 301)
|
assert.Equal(t, 301, w.Code)
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/path")
|
assert.Equal(t, "/path", w.Header().Get("Location"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
|
func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
|
||||||
@ -887,8 +912,8 @@ func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
|
|||||||
c.Redirect(302, "http://google.com")
|
c.Redirect(302, "http://google.com")
|
||||||
c.Writer.WriteHeaderNow()
|
c.Writer.WriteHeaderNow()
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 302)
|
assert.Equal(t, 302, w.Code)
|
||||||
assert.Equal(t, w.Header().Get("Location"), "http://google.com")
|
assert.Equal(t, "http://google.com", w.Header().Get("Location"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextRenderRedirectWith201(t *testing.T) {
|
func TestContextRenderRedirectWith201(t *testing.T) {
|
||||||
@ -899,8 +924,8 @@ func TestContextRenderRedirectWith201(t *testing.T) {
|
|||||||
c.Redirect(201, "/resource")
|
c.Redirect(201, "/resource")
|
||||||
c.Writer.WriteHeaderNow()
|
c.Writer.WriteHeaderNow()
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 201)
|
assert.Equal(t, 201, w.Code)
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/resource")
|
assert.Equal(t, "/resource", w.Header().Get("Location"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextRenderRedirectAll(t *testing.T) {
|
func TestContextRenderRedirectAll(t *testing.T) {
|
||||||
@ -981,8 +1006,8 @@ func TestContextNegotiationFormat(t *testing.T) {
|
|||||||
c.Request, _ = http.NewRequest("POST", "", nil)
|
c.Request, _ = http.NewRequest("POST", "", nil)
|
||||||
|
|
||||||
assert.Panics(t, func() { c.NegotiateFormat() })
|
assert.Panics(t, func() { c.NegotiateFormat() })
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON, MIMEXML), MIMEJSON)
|
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEHTML, MIMEJSON), MIMEHTML)
|
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextNegotiationFormatWithAccept(t *testing.T) {
|
func TestContextNegotiationFormatWithAccept(t *testing.T) {
|
||||||
@ -990,9 +1015,9 @@ func TestContextNegotiationFormatWithAccept(t *testing.T) {
|
|||||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||||
|
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON, MIMEXML), MIMEXML)
|
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEXML, MIMEHTML), MIMEHTML)
|
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEXML, MIMEHTML))
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON), "")
|
assert.Empty(t, c.NegotiateFormat(MIMEJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextNegotiationFormatCustum(t *testing.T) {
|
func TestContextNegotiationFormatCustum(t *testing.T) {
|
||||||
@ -1003,9 +1028,9 @@ func TestContextNegotiationFormatCustum(t *testing.T) {
|
|||||||
c.Accepted = nil
|
c.Accepted = nil
|
||||||
c.SetAccepted(MIMEJSON, MIMEXML)
|
c.SetAccepted(MIMEJSON, MIMEXML)
|
||||||
|
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON, MIMEXML), MIMEJSON)
|
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEXML, MIMEHTML), MIMEXML)
|
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
|
||||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON), MIMEJSON)
|
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextIsAborted(t *testing.T) {
|
func TestContextIsAborted(t *testing.T) {
|
||||||
@ -1031,9 +1056,9 @@ func TestContextAbortWithStatus(t *testing.T) {
|
|||||||
c.index = 4
|
c.index = 4
|
||||||
c.AbortWithStatus(401)
|
c.AbortWithStatus(401)
|
||||||
|
|
||||||
assert.Equal(t, c.index, abortIndex)
|
assert.Equal(t, abortIndex, c.index)
|
||||||
assert.Equal(t, c.Writer.Status(), 401)
|
assert.Equal(t, 401, c.Writer.Status())
|
||||||
assert.Equal(t, w.Code, 401)
|
assert.Equal(t, 401, w.Code)
|
||||||
assert.True(t, c.IsAborted())
|
assert.True(t, c.IsAborted())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,13 +1078,13 @@ func TestContextAbortWithStatusJSON(t *testing.T) {
|
|||||||
|
|
||||||
c.AbortWithStatusJSON(415, in)
|
c.AbortWithStatusJSON(415, in)
|
||||||
|
|
||||||
assert.Equal(t, c.index, abortIndex)
|
assert.Equal(t, abortIndex, c.index)
|
||||||
assert.Equal(t, c.Writer.Status(), 415)
|
assert.Equal(t, 415, c.Writer.Status())
|
||||||
assert.Equal(t, w.Code, 415)
|
assert.Equal(t, 415, w.Code)
|
||||||
assert.True(t, c.IsAborted())
|
assert.True(t, c.IsAborted())
|
||||||
|
|
||||||
contentType := w.Header().Get("Content-Type")
|
contentType := w.Header().Get("Content-Type")
|
||||||
assert.Equal(t, contentType, "application/json; charset=utf-8")
|
assert.Equal(t, "application/json; charset=utf-8", contentType)
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
buf.ReadFrom(w.Body)
|
buf.ReadFrom(w.Body)
|
||||||
@ -1073,7 +1098,7 @@ func TestContextError(t *testing.T) {
|
|||||||
|
|
||||||
c.Error(errors.New("first error"))
|
c.Error(errors.New("first error"))
|
||||||
assert.Len(t, c.Errors, 1)
|
assert.Len(t, c.Errors, 1)
|
||||||
assert.Equal(t, c.Errors.String(), "Error #01: first error\n")
|
assert.Equal(t, "Error #01: first error\n", c.Errors.String())
|
||||||
|
|
||||||
c.Error(&Error{
|
c.Error(&Error{
|
||||||
Err: errors.New("second error"),
|
Err: errors.New("second error"),
|
||||||
@ -1082,13 +1107,13 @@ func TestContextError(t *testing.T) {
|
|||||||
})
|
})
|
||||||
assert.Len(t, c.Errors, 2)
|
assert.Len(t, c.Errors, 2)
|
||||||
|
|
||||||
assert.Equal(t, c.Errors[0].Err, errors.New("first error"))
|
assert.Equal(t, errors.New("first error"), c.Errors[0].Err)
|
||||||
assert.Nil(t, c.Errors[0].Meta)
|
assert.Nil(t, c.Errors[0].Meta)
|
||||||
assert.Equal(t, c.Errors[0].Type, ErrorTypePrivate)
|
assert.Equal(t, ErrorTypePrivate, c.Errors[0].Type)
|
||||||
|
|
||||||
assert.Equal(t, c.Errors[1].Err, errors.New("second error"))
|
assert.Equal(t, errors.New("second error"), c.Errors[1].Err)
|
||||||
assert.Equal(t, c.Errors[1].Meta, "some data 2")
|
assert.Equal(t, "some data 2", c.Errors[1].Meta)
|
||||||
assert.Equal(t, c.Errors[1].Type, ErrorTypePublic)
|
assert.Equal(t, ErrorTypePublic, c.Errors[1].Type)
|
||||||
|
|
||||||
assert.Equal(t, c.Errors.Last(), c.Errors[1])
|
assert.Equal(t, c.Errors.Last(), c.Errors[1])
|
||||||
|
|
||||||
@ -1106,12 +1131,12 @@ func TestContextTypedError(t *testing.T) {
|
|||||||
c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate)
|
c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate)
|
||||||
|
|
||||||
for _, err := range c.Errors.ByType(ErrorTypePublic) {
|
for _, err := range c.Errors.ByType(ErrorTypePublic) {
|
||||||
assert.Equal(t, err.Type, ErrorTypePublic)
|
assert.Equal(t, ErrorTypePublic, err.Type)
|
||||||
}
|
}
|
||||||
for _, err := range c.Errors.ByType(ErrorTypePrivate) {
|
for _, err := range c.Errors.ByType(ErrorTypePrivate) {
|
||||||
assert.Equal(t, err.Type, ErrorTypePrivate)
|
assert.Equal(t, ErrorTypePrivate, err.Type)
|
||||||
}
|
}
|
||||||
assert.Equal(t, c.Errors.Errors(), []string{"externo 0", "interno 0"})
|
assert.Equal(t, []string{"externo 0", "interno 0"}, c.Errors.Errors())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextAbortWithError(t *testing.T) {
|
func TestContextAbortWithError(t *testing.T) {
|
||||||
@ -1120,8 +1145,8 @@ func TestContextAbortWithError(t *testing.T) {
|
|||||||
|
|
||||||
c.AbortWithError(401, errors.New("bad input")).SetMeta("some input")
|
c.AbortWithError(401, errors.New("bad input")).SetMeta("some input")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 401)
|
assert.Equal(t, 401, w.Code)
|
||||||
assert.Equal(t, c.index, abortIndex)
|
assert.Equal(t, abortIndex, c.index)
|
||||||
assert.True(t, c.IsAborted())
|
assert.True(t, c.IsAborted())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,7 +1177,7 @@ func TestContextClientIP(t *testing.T) {
|
|||||||
|
|
||||||
// no port
|
// no port
|
||||||
c.Request.RemoteAddr = "50.50.50.50"
|
c.Request.RemoteAddr = "50.50.50.50"
|
||||||
assert.Equal(t, "", c.ClientIP())
|
assert.Empty(t, c.ClientIP())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextContentType(t *testing.T) {
|
func TestContextContentType(t *testing.T) {
|
||||||
@ -1160,7 +1185,7 @@ func TestContextContentType(t *testing.T) {
|
|||||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||||
c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
|
c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
|
||||||
assert.Equal(t, c.ContentType(), "application/json")
|
assert.Equal(t, "application/json", c.ContentType())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextAutoBindJSON(t *testing.T) {
|
func TestContextAutoBindJSON(t *testing.T) {
|
||||||
@ -1173,8 +1198,8 @@ func TestContextAutoBindJSON(t *testing.T) {
|
|||||||
Bar string `json:"bar"`
|
Bar string `json:"bar"`
|
||||||
}
|
}
|
||||||
assert.NoError(t, c.Bind(&obj))
|
assert.NoError(t, c.Bind(&obj))
|
||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, "foo", obj.Bar)
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, "bar", obj.Foo)
|
||||||
assert.Empty(t, c.Errors)
|
assert.Empty(t, c.Errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,9 +1215,9 @@ func TestContextBindWithJSON(t *testing.T) {
|
|||||||
Bar string `json:"bar"`
|
Bar string `json:"bar"`
|
||||||
}
|
}
|
||||||
assert.NoError(t, c.BindJSON(&obj))
|
assert.NoError(t, c.BindJSON(&obj))
|
||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, "foo", obj.Bar)
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, "bar", obj.Foo)
|
||||||
assert.Equal(t, w.Body.Len(), 0)
|
assert.Equal(t, 0, w.Body.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextBindWithQuery(t *testing.T) {
|
func TestContextBindWithQuery(t *testing.T) {
|
||||||
@ -1228,7 +1253,7 @@ func TestContextBadAutoBind(t *testing.T) {
|
|||||||
|
|
||||||
assert.Empty(t, obj.Bar)
|
assert.Empty(t, obj.Bar)
|
||||||
assert.Empty(t, obj.Foo)
|
assert.Empty(t, obj.Foo)
|
||||||
assert.Equal(t, w.Code, 400)
|
assert.Equal(t, 400, w.Code)
|
||||||
assert.True(t, c.IsAborted())
|
assert.True(t, c.IsAborted())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1242,8 +1267,8 @@ func TestContextAutoShouldBindJSON(t *testing.T) {
|
|||||||
Bar string `json:"bar"`
|
Bar string `json:"bar"`
|
||||||
}
|
}
|
||||||
assert.NoError(t, c.ShouldBind(&obj))
|
assert.NoError(t, c.ShouldBind(&obj))
|
||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, "foo", obj.Bar)
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, "bar", obj.Foo)
|
||||||
assert.Empty(t, c.Errors)
|
assert.Empty(t, c.Errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,9 +1284,9 @@ func TestContextShouldBindWithJSON(t *testing.T) {
|
|||||||
Bar string `json:"bar"`
|
Bar string `json:"bar"`
|
||||||
}
|
}
|
||||||
assert.NoError(t, c.ShouldBindJSON(&obj))
|
assert.NoError(t, c.ShouldBindJSON(&obj))
|
||||||
assert.Equal(t, obj.Bar, "foo")
|
assert.Equal(t, "foo", obj.Bar)
|
||||||
assert.Equal(t, obj.Foo, "bar")
|
assert.Equal(t, "bar", obj.Foo)
|
||||||
assert.Equal(t, w.Body.Len(), 0)
|
assert.Equal(t, 0, w.Body.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextShouldBindWithQuery(t *testing.T) {
|
func TestContextShouldBindWithQuery(t *testing.T) {
|
||||||
@ -1311,7 +1336,7 @@ func TestContextGolangContext(t *testing.T) {
|
|||||||
assert.Nil(t, c.Value("foo"))
|
assert.Nil(t, c.Value("foo"))
|
||||||
|
|
||||||
c.Set("foo", "bar")
|
c.Set("foo", "bar")
|
||||||
assert.Equal(t, c.Value("foo"), "bar")
|
assert.Equal(t, "bar", c.Value("foo"))
|
||||||
assert.Nil(t, c.Value(1))
|
assert.Nil(t, c.Value(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1343,7 +1368,7 @@ func TestGetRequestHeaderValue(t *testing.T) {
|
|||||||
c.Request.Header.Set("Gin-Version", "1.0.0")
|
c.Request.Header.Set("Gin-Version", "1.0.0")
|
||||||
|
|
||||||
assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
|
assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
|
||||||
assert.Equal(t, "", c.GetHeader("Connection"))
|
assert.Empty(t, c.GetHeader("Connection"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContextGetRawData(t *testing.T) {
|
func TestContextGetRawData(t *testing.T) {
|
||||||
|
13
coverage.sh
Normal file
13
coverage.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "mode: count" > coverage.out
|
||||||
|
|
||||||
|
for d in $(go list ./... | grep -E 'gin$|binding$|render$'); do
|
||||||
|
go test -v -covermode=count -coverprofile=profile.out $d
|
||||||
|
if [ -f profile.out ]; then
|
||||||
|
cat profile.out | grep -v "mode:" >> coverage.out
|
||||||
|
rm profile.out
|
||||||
|
fi
|
||||||
|
done
|
2
debug.go
2
debug.go
@ -19,7 +19,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsDebugging returns true if the framework is running in debug mode.
|
// IsDebugging returns true if the framework is running in debug mode.
|
||||||
// Use SetMode(gin.Release) to disable debug mode.
|
// Use SetMode(gin.ReleaseMode) to disable debug mode.
|
||||||
func IsDebugging() bool {
|
func IsDebugging() bool {
|
||||||
return ginMode == debugCode
|
return ginMode == debugCode
|
||||||
}
|
}
|
||||||
|
31
deprecated_test.go
Normal file
31
deprecated_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin/binding"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBindWith(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
|
||||||
|
|
||||||
|
var obj struct {
|
||||||
|
Foo string `form:"foo"`
|
||||||
|
Bar string `form:"bar"`
|
||||||
|
}
|
||||||
|
assert.NoError(t, c.BindWith(&obj, binding.Form))
|
||||||
|
assert.Equal(t, "foo", obj.Bar)
|
||||||
|
assert.Equal(t, "bar", obj.Foo)
|
||||||
|
assert.Equal(t, 0, w.Body.Len())
|
||||||
|
}
|
@ -148,7 +148,7 @@ func (a errorMsgs) String() string {
|
|||||||
}
|
}
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
for i, msg := range a {
|
for i, msg := range a {
|
||||||
fmt.Fprintf(&buffer, "Error #%02d: %s\n", (i + 1), msg.Err)
|
fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err)
|
||||||
if msg.Meta != nil {
|
if msg.Meta != nil {
|
||||||
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
|
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
var DB = make(map[string]string)
|
var DB = make(map[string]string)
|
||||||
|
|
||||||
func main() {
|
func setupRouter() *gin.Engine {
|
||||||
// Disable Console Color
|
// Disable Console Color
|
||||||
// gin.DisableConsoleColor()
|
// gin.DisableConsoleColor()
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
@ -53,6 +53,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := setupRouter()
|
||||||
// Listen and Server in 0.0.0.0:8080
|
// Listen and Server in 0.0.0.0:8080
|
||||||
r.Run(":8080")
|
r.Run(":8080")
|
||||||
}
|
}
|
||||||
|
20
examples/basic/main_test.go
Normal file
20
examples/basic/main_test.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPingRoute(t *testing.T) {
|
||||||
|
router := setupRouter()
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req, _ := http.NewRequest("GET", "/ping", nil)
|
||||||
|
router.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
assert.Equal(t, 200, w.Code)
|
||||||
|
assert.Equal(t, "pong", w.Body.String())
|
||||||
|
}
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
validator "gopkg.in/go-playground/validator.v8"
|
"gopkg.in/go-playground/validator.v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Booking struct {
|
type Booking struct {
|
||||||
|
@ -29,8 +29,8 @@ func statsWorker() {
|
|||||||
"timestamp": uint64(time.Now().Unix()),
|
"timestamp": uint64(time.Now().Unix()),
|
||||||
"HeapInuse": stats.HeapInuse,
|
"HeapInuse": stats.HeapInuse,
|
||||||
"StackInuse": stats.StackInuse,
|
"StackInuse": stats.StackInuse,
|
||||||
"Mallocs": (stats.Mallocs - lastMallocs),
|
"Mallocs": stats.Mallocs - lastMallocs,
|
||||||
"Frees": (stats.Frees - lastFrees),
|
"Frees": stats.Frees - lastFrees,
|
||||||
"Inbound": uint64(messages.Get("inbound")),
|
"Inbound": uint64(messages.Get("inbound")),
|
||||||
"Outbound": uint64(messages.Get("outbound")),
|
"Outbound": uint64(messages.Get("outbound")),
|
||||||
"Connected": connectedUsers(),
|
"Connected": connectedUsers(),
|
||||||
|
18
fixtures/testdata/cert.pem
vendored
Normal file
18
fixtures/testdata/cert.pem
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC9DCCAdygAwIBAgIQUNSK+OxWHYYFxHVJV0IlpDANBgkqhkiG9w0BAQsFADAS
|
||||||
|
MRAwDgYDVQQKEwdBY21lIENvMB4XDTE3MTExNjEyMDA0N1oXDTE4MTExNjEyMDA0
|
||||||
|
N1owEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||||
|
AQoCggEBAKmyj/YZpD59Bpy4w3qf6VzMw9uUBsWp+IP4kl7z5cmGHYUHn/YopTLH
|
||||||
|
vR23GAB12p6Km5QWzCBuJF4j61PJXHfg3/rjShZ77JcQ3kzxuy1iKDI+DNKN7Klz
|
||||||
|
rdjJ49QD0lczZHeBvvCL7JsJFKFjGy62rnStuW8LaIEdtjXT+GUZTxJh6G7yPYfD
|
||||||
|
MS1IsdMQGOdbGwNa+qogMuQPh0TzHw+C73myKrjY6pREijknMC/rnIMz9dLPt6Kl
|
||||||
|
xXy4br443dpY6dYGIhDuKhROT+vZ05HKasuuQUFhY7v/KoUpEZMB9rfUSzjQ5fak
|
||||||
|
eDUAMniXRcd+DmwvboG2TI6ixmuPK+ECAwEAAaNGMEQwDgYDVR0PAQH/BAQDAgWg
|
||||||
|
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDwYDVR0RBAgwBocE
|
||||||
|
fwAAATANBgkqhkiG9w0BAQsFAAOCAQEAMXOLvj7BFsxdbcfRPBd0OFrH/8lI7vPV
|
||||||
|
LRcJ6r5iv0cnNvZXXbIOQLbg4clJAWjoE08nRm1KvNXhKdns0ELEV86YN2S6jThq
|
||||||
|
rIGrBqKtaJLB3M9BtDSiQ6SGPLYrWvmhj3Avi8PbSGy51bpGbqopd16j6LYU7Cp2
|
||||||
|
TefMRlOAFtHojpCVon1CMpqcNxS0WNlQ3lUBSrw3HB0o12x++roja2ibF54tSHXB
|
||||||
|
KUuadoEzN+mMBwenEBychmAGzdiG4GQHRmhigh85+mtW6UMGiqyCZHs0EgE9FCLL
|
||||||
|
sRrsTI/VOzLz6lluygXkOsXrP+PP0SvmE3eylWjj9e2nj/u/Cy2YKg==
|
||||||
|
-----END CERTIFICATE-----
|
27
fixtures/testdata/key.pem
vendored
Normal file
27
fixtures/testdata/key.pem
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEogIBAAKCAQEAqbKP9hmkPn0GnLjDep/pXMzD25QGxan4g/iSXvPlyYYdhQef
|
||||||
|
9iilMse9HbcYAHXanoqblBbMIG4kXiPrU8lcd+Df+uNKFnvslxDeTPG7LWIoMj4M
|
||||||
|
0o3sqXOt2Mnj1APSVzNkd4G+8IvsmwkUoWMbLraudK25bwtogR22NdP4ZRlPEmHo
|
||||||
|
bvI9h8MxLUix0xAY51sbA1r6qiAy5A+HRPMfD4LvebIquNjqlESKOScwL+ucgzP1
|
||||||
|
0s+3oqXFfLhuvjjd2ljp1gYiEO4qFE5P69nTkcpqy65BQWFju/8qhSkRkwH2t9RL
|
||||||
|
ONDl9qR4NQAyeJdFx34ObC9ugbZMjqLGa48r4QIDAQABAoIBAD5mhd+GMEo2KU9J
|
||||||
|
9b/Ku8I/HapJtW/L/7Fvn0tBPncrVQGM+zpGWfDhV95sbGwG6lwwNeNvuqIWPlNL
|
||||||
|
vAY0XkdKrrIQEDdSXH50WnpKzXxzwrou7QIj5Cmvevbjzl4xBZDBOilj0XWczmV4
|
||||||
|
IljyG5XC4UXQeAaoWEZaSZ1jk8yAt2Zq1Hgg7HqhHsK/arWXBgax+4K5nV/s9gZx
|
||||||
|
yjKU9mXTIs7k/aNnZqwQKqcZF+l3mvbZttOaFwsP14H0I8OFWhnM9hie54Dejqxi
|
||||||
|
f4/llNxDqUs6lqJfP3qNxtORLcFe75M+Yl8v7g2hkjtLdZBakPzSTEx3TAK/UHgi
|
||||||
|
aM8DdxECgYEA3fmg/PI4EgUEj0C3SCmQXR/CnQLMUQgb54s0asp4akvp+M7YCcr1
|
||||||
|
pQd3HFUpBwhBcJg5LeSe87vLupY7pHCKk56cl9WY6hse0b9sP/7DWJuGiO62m0E0
|
||||||
|
vNjQ2jpG99oR2ROIHHeWsGCpGLmrRT/kY+vR3M+AOLZniXlOCw8k0aUCgYEAw7WL
|
||||||
|
XFWLxgZYQYilywqrQmfv1MBfaUCvykO6oWB+f6mmnihSFjecI+nDw/b3yXVYGEgy
|
||||||
|
0ebkuw0jP8suC8wBqX9WuXj+9nZNomJRssJyOMiEhDEqUiTztFPSp9pdruoakLTh
|
||||||
|
Wk1p9NralOqGPUmxpXlFKVmYRTUbluikVxDypI0CgYBn6sqEQH0hann0+o4TWWn9
|
||||||
|
PrYkPUAbm1k8771tVTZERR/W3Dbldr/DL5iCihe39BR2urziEEqdvkglJNntJMar
|
||||||
|
TzDuIBADYQjvltb9qq4XGFBGYMLaMg+XbUVxNKEuvUdnwa4R7aZ9EfN34MwekkfA
|
||||||
|
w5Cu9/GGG1ajVEfGA6PwBQKBgA3o71jGs8KFXOx7e90sivOTU5Z5fc6LTHNB0Rf7
|
||||||
|
NcJ5GmCPWRY/KZfb25AoE4B8GKDRMNt+X69zxZeZJ1KrU0rqxA02rlhyHB54gnoE
|
||||||
|
G/4xMkn6/JkOC0w70PMhMBtohC7YzFOQwQEoNPT0nkno3Pl33xSLS6lPlwBo1JVj
|
||||||
|
nPtZAoGACXNLXYkR5vexE+w6FGl59r4RQhu1XU8Mr5DIHeB7kXPN3RKbS201M+Tb
|
||||||
|
SB5jbu0iDV477XkzSNmhaksFf2wM9MT6CaE+8n3UU5tMa+MmBGgwYTp/i9HkqVh5
|
||||||
|
jjpJifn1VWBINd4cpNzwCg9LXoo0tbtUPWwGzqVeyo/YE5GIHGo=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
34
gin.go
34
gin.go
@ -14,8 +14,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin/render"
|
"github.com/gin-gonic/gin/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version is Framework's version.
|
|
||||||
const (
|
const (
|
||||||
|
// Version is Framework's version.
|
||||||
Version = "v1.2"
|
Version = "v1.2"
|
||||||
defaultMultipartMemory = 32 << 20 // 32 MB
|
defaultMultipartMemory = 32 << 20 // 32 MB
|
||||||
)
|
)
|
||||||
@ -49,16 +49,6 @@ type RoutesInfo []RouteInfo
|
|||||||
// Create an instance of Engine, by using New() or Default()
|
// Create an instance of Engine, by using New() or Default()
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
RouterGroup
|
RouterGroup
|
||||||
delims render.Delims
|
|
||||||
secureJsonPrefix string
|
|
||||||
HTMLRender render.HTMLRender
|
|
||||||
FuncMap template.FuncMap
|
|
||||||
allNoRoute HandlersChain
|
|
||||||
allNoMethod HandlersChain
|
|
||||||
noRoute HandlersChain
|
|
||||||
noMethod HandlersChain
|
|
||||||
pool sync.Pool
|
|
||||||
trees methodTrees
|
|
||||||
|
|
||||||
// Enables automatic redirection if the current route can't be matched but a
|
// Enables automatic redirection if the current route can't be matched but a
|
||||||
// handler for the path with (without) the trailing slash exists.
|
// handler for the path with (without) the trailing slash exists.
|
||||||
@ -102,6 +92,17 @@ type Engine struct {
|
|||||||
// Value of 'maxMemory' param that is given to http.Request's ParseMultipartForm
|
// Value of 'maxMemory' param that is given to http.Request's ParseMultipartForm
|
||||||
// method call.
|
// method call.
|
||||||
MaxMultipartMemory int64
|
MaxMultipartMemory int64
|
||||||
|
|
||||||
|
delims render.Delims
|
||||||
|
secureJsonPrefix string
|
||||||
|
HTMLRender render.HTMLRender
|
||||||
|
FuncMap template.FuncMap
|
||||||
|
allNoRoute HandlersChain
|
||||||
|
allNoMethod HandlersChain
|
||||||
|
noRoute HandlersChain
|
||||||
|
noMethod HandlersChain
|
||||||
|
pool sync.Pool
|
||||||
|
trees methodTrees
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ IRouter = &Engine{}
|
var _ IRouter = &Engine{}
|
||||||
@ -159,11 +160,14 @@ func (engine *Engine) Delims(left, right string) *Engine {
|
|||||||
return engine
|
return engine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SecureJsonPrefix sets the secureJsonPrefix used in Context.SecureJSON.
|
||||||
func (engine *Engine) SecureJsonPrefix(prefix string) *Engine {
|
func (engine *Engine) SecureJsonPrefix(prefix string) *Engine {
|
||||||
engine.secureJsonPrefix = prefix
|
engine.secureJsonPrefix = prefix
|
||||||
return engine
|
return engine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadHTMLGlob loads HTML files identified by glob pattern
|
||||||
|
// and associates the result with HTML renderer.
|
||||||
func (engine *Engine) LoadHTMLGlob(pattern string) {
|
func (engine *Engine) LoadHTMLGlob(pattern string) {
|
||||||
left := engine.delims.Left
|
left := engine.delims.Left
|
||||||
right := engine.delims.Right
|
right := engine.delims.Right
|
||||||
@ -178,6 +182,8 @@ func (engine *Engine) LoadHTMLGlob(pattern string) {
|
|||||||
engine.SetHTMLTemplate(templ)
|
engine.SetHTMLTemplate(templ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadHTMLFiles loads a slice of HTML files
|
||||||
|
// and associates the result with HTML renderer.
|
||||||
func (engine *Engine) LoadHTMLFiles(files ...string) {
|
func (engine *Engine) LoadHTMLFiles(files ...string) {
|
||||||
if IsDebugging() {
|
if IsDebugging() {
|
||||||
engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims}
|
engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims}
|
||||||
@ -188,6 +194,7 @@ func (engine *Engine) LoadHTMLFiles(files ...string) {
|
|||||||
engine.SetHTMLTemplate(templ)
|
engine.SetHTMLTemplate(templ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHTMLTemplate associate a template with HTML renderer.
|
||||||
func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
|
func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
|
||||||
if len(engine.trees) > 0 {
|
if len(engine.trees) > 0 {
|
||||||
debugPrintWARNINGSetHTMLTemplate()
|
debugPrintWARNINGSetHTMLTemplate()
|
||||||
@ -196,6 +203,7 @@ func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
|
|||||||
engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)}
|
engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFuncMap sets the FuncMap used for template.FuncMap.
|
||||||
func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
|
func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
|
||||||
engine.FuncMap = funcMap
|
engine.FuncMap = funcMap
|
||||||
}
|
}
|
||||||
@ -403,8 +411,8 @@ func redirectTrailingSlash(c *Context) {
|
|||||||
code = 307
|
code = 307
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(path) > 1 && path[len(path)-1] == '/' {
|
if length := len(path); length > 1 && path[length-1] == '/' {
|
||||||
req.URL.Path = path[:len(path)-1]
|
req.URL.Path = path[:length-1]
|
||||||
} else {
|
} else {
|
||||||
req.URL.Path = path + "/"
|
req.URL.Path = path + "/"
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ func TestUnixSocket(t *testing.T) {
|
|||||||
c, err := net.Dial("unix", "/tmp/unix_unit_test")
|
c, err := net.Dial("unix", "/tmp/unix_unit_test")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
fmt.Fprintf(c, "GET /example HTTP/1.0\r\n\r\n")
|
fmt.Fprint(c, "GET /example HTTP/1.0\r\n\r\n")
|
||||||
scanner := bufio.NewScanner(c)
|
scanner := bufio.NewScanner(c)
|
||||||
var response string
|
var response string
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
|
128
gin_test.go
128
gin_test.go
@ -5,6 +5,7 @@
|
|||||||
package gin
|
package gin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -21,9 +22,9 @@ func formatAsDate(t time.Time) string {
|
|||||||
return fmt.Sprintf("%d/%02d/%02d", year, month, day)
|
return fmt.Sprintf("%d/%02d/%02d", year, month, day)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupHTMLFiles(t *testing.T) func() {
|
func setupHTMLFiles(t *testing.T, mode string, tls bool) func() {
|
||||||
go func() {
|
go func() {
|
||||||
SetMode(TestMode)
|
SetMode(mode)
|
||||||
router := New()
|
router := New()
|
||||||
router.Delims("{[{", "}]}")
|
router.Delims("{[{", "}]}")
|
||||||
router.SetFuncMap(template.FuncMap{
|
router.SetFuncMap(template.FuncMap{
|
||||||
@ -38,16 +39,21 @@ func setupHTMLFiles(t *testing.T) func() {
|
|||||||
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
|
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
if tls {
|
||||||
|
// these files generated by `go run $GOROOT/src/crypto/tls/generate_cert.go --host 127.0.0.1`
|
||||||
|
router.RunTLS(":9999", "./fixtures/testdata/cert.pem", "./fixtures/testdata/key.pem")
|
||||||
|
} else {
|
||||||
router.Run(":8888")
|
router.Run(":8888")
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
t.Log("waiting 1 second for server startup")
|
t.Log("waiting 1 second for server startup")
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
return func() {}
|
return func() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupHTMLGlob(t *testing.T) func() {
|
func setupHTMLGlob(t *testing.T, mode string, tls bool) func() {
|
||||||
go func() {
|
go func() {
|
||||||
SetMode(DebugMode)
|
SetMode(mode)
|
||||||
router := New()
|
router := New()
|
||||||
router.Delims("{[{", "}]}")
|
router.Delims("{[{", "}]}")
|
||||||
router.SetFuncMap(template.FuncMap{
|
router.SetFuncMap(template.FuncMap{
|
||||||
@ -62,16 +68,20 @@ func setupHTMLGlob(t *testing.T) func() {
|
|||||||
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
|
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
if tls {
|
||||||
|
// these files generated by `go run $GOROOT/src/crypto/tls/generate_cert.go --host 127.0.0.1`
|
||||||
|
router.RunTLS(":9999", "./fixtures/testdata/cert.pem", "./fixtures/testdata/key.pem")
|
||||||
|
} else {
|
||||||
router.Run(":8888")
|
router.Run(":8888")
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
t.Log("waiting 1 second for server startup")
|
t.Log("waiting 1 second for server startup")
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
return func() {}
|
return func() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO
|
|
||||||
func TestLoadHTMLGlob(t *testing.T) {
|
func TestLoadHTMLGlob(t *testing.T) {
|
||||||
td := setupHTMLGlob(t)
|
td := setupHTMLGlob(t, DebugMode, false)
|
||||||
res, err := http.Get("http://127.0.0.1:8888/test")
|
res, err := http.Get("http://127.0.0.1:8888/test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -83,9 +93,55 @@ func TestLoadHTMLGlob(t *testing.T) {
|
|||||||
td()
|
td()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadHTMLGlob2(t *testing.T) {
|
||||||
|
td := setupHTMLGlob(t, TestMode, false)
|
||||||
|
res, err := http.Get("http://127.0.0.1:8888/test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := ioutil.ReadAll(res.Body)
|
||||||
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp[:]))
|
||||||
|
|
||||||
|
td()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadHTMLGlob3(t *testing.T) {
|
||||||
|
td := setupHTMLGlob(t, ReleaseMode, false)
|
||||||
|
res, err := http.Get("http://127.0.0.1:8888/test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := ioutil.ReadAll(res.Body)
|
||||||
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp[:]))
|
||||||
|
|
||||||
|
td()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadHTMLGlobUsingTLS(t *testing.T) {
|
||||||
|
td := setupHTMLGlob(t, DebugMode, true)
|
||||||
|
// Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
res, err := client.Get("https://127.0.0.1:9999/test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := ioutil.ReadAll(res.Body)
|
||||||
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp[:]))
|
||||||
|
|
||||||
|
td()
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
|
func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
|
||||||
time.Now()
|
time.Now()
|
||||||
td := setupHTMLGlob(t)
|
td := setupHTMLGlob(t, DebugMode, false)
|
||||||
res, err := http.Get("http://127.0.0.1:8888/raw")
|
res, err := http.Get("http://127.0.0.1:8888/raw")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -97,9 +153,6 @@ func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
|
|||||||
td()
|
td()
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (engine *Engine) LoadHTMLFiles(files ...string) {
|
|
||||||
// func (engine *Engine) RunTLS(addr string, cert string, key string) error {
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
SetMode(TestMode)
|
SetMode(TestMode)
|
||||||
}
|
}
|
||||||
@ -117,17 +170,17 @@ func TestCreateEngine(t *testing.T) {
|
|||||||
// router.LoadHTMLGlob("*.testtmpl")
|
// router.LoadHTMLGlob("*.testtmpl")
|
||||||
// r := router.HTMLRender.(render.HTMLDebug)
|
// r := router.HTMLRender.(render.HTMLDebug)
|
||||||
// assert.Empty(t, r.Files)
|
// assert.Empty(t, r.Files)
|
||||||
// assert.Equal(t, r.Glob, "*.testtmpl")
|
// assert.Equal(t, "*.testtmpl", r.Glob)
|
||||||
//
|
//
|
||||||
// router.LoadHTMLFiles("index.html.testtmpl", "login.html.testtmpl")
|
// router.LoadHTMLFiles("index.html.testtmpl", "login.html.testtmpl")
|
||||||
// r = router.HTMLRender.(render.HTMLDebug)
|
// r = router.HTMLRender.(render.HTMLDebug)
|
||||||
// assert.Empty(t, r.Glob)
|
// assert.Empty(t, r.Glob)
|
||||||
// assert.Equal(t, r.Files, []string{"index.html", "login.html"})
|
// assert.Equal(t, []string{"index.html", "login.html"}, r.Files)
|
||||||
// SetMode(TestMode)
|
// SetMode(TestMode)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func TestLoadHTMLFiles(t *testing.T) {
|
func TestLoadHTMLFiles(t *testing.T) {
|
||||||
td := setupHTMLFiles(t)
|
td := setupHTMLFiles(t, TestMode, false)
|
||||||
res, err := http.Get("http://127.0.0.1:8888/test")
|
res, err := http.Get("http://127.0.0.1:8888/test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -138,9 +191,52 @@ func TestLoadHTMLFiles(t *testing.T) {
|
|||||||
td()
|
td()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadHTMLFiles2(t *testing.T) {
|
||||||
|
td := setupHTMLFiles(t, DebugMode, false)
|
||||||
|
res, err := http.Get("http://127.0.0.1:8888/test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := ioutil.ReadAll(res.Body)
|
||||||
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp[:]))
|
||||||
|
td()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadHTMLFiles3(t *testing.T) {
|
||||||
|
td := setupHTMLFiles(t, ReleaseMode, false)
|
||||||
|
res, err := http.Get("http://127.0.0.1:8888/test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := ioutil.ReadAll(res.Body)
|
||||||
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp[:]))
|
||||||
|
td()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadHTMLFilesUsingTLS(t *testing.T) {
|
||||||
|
td := setupHTMLFiles(t, TestMode, true)
|
||||||
|
// Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
res, err := client.Get("https://127.0.0.1:9999/test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := ioutil.ReadAll(res.Body)
|
||||||
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp[:]))
|
||||||
|
td()
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadHTMLFilesFuncMap(t *testing.T) {
|
func TestLoadHTMLFilesFuncMap(t *testing.T) {
|
||||||
time.Now()
|
time.Now()
|
||||||
td := setupHTMLFiles(t)
|
td := setupHTMLFiles(t, TestMode, false)
|
||||||
res, err := http.Get("http://127.0.0.1:8888/raw")
|
res, err := http.Get("http://127.0.0.1:8888/raw")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -152,10 +248,6 @@ func TestLoadHTMLFilesFuncMap(t *testing.T) {
|
|||||||
td()
|
td()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadHTMLReleaseMode(t *testing.T) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddRoute(t *testing.T) {
|
func TestAddRoute(t *testing.T) {
|
||||||
router := New()
|
router := New()
|
||||||
router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
|
router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
|
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import "encoding/json"
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Marshal = json.Marshal
|
Marshal = json.Marshal
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
|
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import "github.com/json-iterator/go"
|
||||||
"github.com/json-iterator/go"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
json = jsoniter.ConfigCompatibleWithStandardLibrary
|
json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
@ -82,21 +82,21 @@ func TestLogger(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestColorForMethod(t *testing.T) {
|
func TestColorForMethod(t *testing.T) {
|
||||||
assert.Equal(t, colorForMethod("GET"), string([]byte{27, 91, 57, 55, 59, 52, 52, 109}), "get should be blue")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 52, 109}), colorForMethod("GET"), "get should be blue")
|
||||||
assert.Equal(t, colorForMethod("POST"), string([]byte{27, 91, 57, 55, 59, 52, 54, 109}), "post should be cyan")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 54, 109}), colorForMethod("POST"), "post should be cyan")
|
||||||
assert.Equal(t, colorForMethod("PUT"), string([]byte{27, 91, 57, 55, 59, 52, 51, 109}), "put should be yellow")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 51, 109}), colorForMethod("PUT"), "put should be yellow")
|
||||||
assert.Equal(t, colorForMethod("DELETE"), string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), "delete should be red")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), colorForMethod("DELETE"), "delete should be red")
|
||||||
assert.Equal(t, colorForMethod("PATCH"), string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), "patch should be green")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), colorForMethod("PATCH"), "patch should be green")
|
||||||
assert.Equal(t, colorForMethod("HEAD"), string([]byte{27, 91, 57, 55, 59, 52, 53, 109}), "head should be magenta")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 53, 109}), colorForMethod("HEAD"), "head should be magenta")
|
||||||
assert.Equal(t, colorForMethod("OPTIONS"), string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), "options should be white")
|
assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), colorForMethod("OPTIONS"), "options should be white")
|
||||||
assert.Equal(t, colorForMethod("TRACE"), string([]byte{27, 91, 48, 109}), "trace is not defined and should be the reset color")
|
assert.Equal(t, string([]byte{27, 91, 48, 109}), colorForMethod("TRACE"), "trace is not defined and should be the reset color")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestColorForStatus(t *testing.T) {
|
func TestColorForStatus(t *testing.T) {
|
||||||
assert.Equal(t, colorForStatus(200), string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), "2xx should be green")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), colorForStatus(200), "2xx should be green")
|
||||||
assert.Equal(t, colorForStatus(301), string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), "3xx should be white")
|
assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), colorForStatus(301), "3xx should be white")
|
||||||
assert.Equal(t, colorForStatus(404), string([]byte{27, 91, 57, 55, 59, 52, 51, 109}), "4xx should be yellow")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 51, 109}), colorForStatus(404), "4xx should be yellow")
|
||||||
assert.Equal(t, colorForStatus(2), string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), "other things should be red")
|
assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), colorForStatus(2), "other things should be red")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorLogger(t *testing.T) {
|
func TestErrorLogger(t *testing.T) {
|
||||||
|
12
mode.go
12
mode.go
@ -14,9 +14,9 @@ import (
|
|||||||
const ENV_GIN_MODE = "GIN_MODE"
|
const ENV_GIN_MODE = "GIN_MODE"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DebugMode string = "debug"
|
DebugMode = "debug"
|
||||||
ReleaseMode string = "release"
|
ReleaseMode = "release"
|
||||||
TestMode string = "test"
|
TestMode = "test"
|
||||||
)
|
)
|
||||||
const (
|
const (
|
||||||
debugCode = iota
|
debugCode = iota
|
||||||
@ -39,16 +39,12 @@ var modeName = DebugMode
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
mode := os.Getenv(ENV_GIN_MODE)
|
mode := os.Getenv(ENV_GIN_MODE)
|
||||||
if mode == "" {
|
|
||||||
SetMode(DebugMode)
|
|
||||||
} else {
|
|
||||||
SetMode(mode)
|
SetMode(mode)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func SetMode(value string) {
|
func SetMode(value string) {
|
||||||
switch value {
|
switch value {
|
||||||
case DebugMode:
|
case DebugMode, "":
|
||||||
ginMode = debugCode
|
ginMode = debugCode
|
||||||
case ReleaseMode:
|
case ReleaseMode:
|
||||||
ginMode = releaseCode
|
ginMode = releaseCode
|
||||||
|
16
mode_test.go
16
mode_test.go
@ -17,21 +17,21 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSetMode(t *testing.T) {
|
func TestSetMode(t *testing.T) {
|
||||||
assert.Equal(t, ginMode, testCode)
|
assert.Equal(t, testCode, ginMode)
|
||||||
assert.Equal(t, Mode(), TestMode)
|
assert.Equal(t, TestMode, Mode())
|
||||||
os.Unsetenv(ENV_GIN_MODE)
|
os.Unsetenv(ENV_GIN_MODE)
|
||||||
|
|
||||||
SetMode(DebugMode)
|
SetMode(DebugMode)
|
||||||
assert.Equal(t, ginMode, debugCode)
|
assert.Equal(t, debugCode, ginMode)
|
||||||
assert.Equal(t, Mode(), DebugMode)
|
assert.Equal(t, DebugMode, Mode())
|
||||||
|
|
||||||
SetMode(ReleaseMode)
|
SetMode(ReleaseMode)
|
||||||
assert.Equal(t, ginMode, releaseCode)
|
assert.Equal(t, releaseCode, ginMode)
|
||||||
assert.Equal(t, Mode(), ReleaseMode)
|
assert.Equal(t, ReleaseMode, Mode())
|
||||||
|
|
||||||
SetMode(TestMode)
|
SetMode(TestMode)
|
||||||
assert.Equal(t, ginMode, testCode)
|
assert.Equal(t, testCode, ginMode)
|
||||||
assert.Equal(t, Mode(), TestMode)
|
assert.Equal(t, TestMode, Mode())
|
||||||
|
|
||||||
assert.Panics(t, func() { SetMode("unknown") })
|
assert.Panics(t, func() { SetMode("unknown") })
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,8 @@ var cleanTests = []struct {
|
|||||||
|
|
||||||
func TestPathClean(t *testing.T) {
|
func TestPathClean(t *testing.T) {
|
||||||
for _, test := range cleanTests {
|
for _, test := range cleanTests {
|
||||||
assert.Equal(t, cleanPath(test.path), test.result)
|
assert.Equal(t, test.result, cleanPath(test.path))
|
||||||
assert.Equal(t, cleanPath(test.result), test.result)
|
assert.Equal(t, test.result, cleanPath(test.result))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ func TestPanicInHandler(t *testing.T) {
|
|||||||
// RUN
|
// RUN
|
||||||
w := performRequest(router, "GET", "/recovery")
|
w := performRequest(router, "GET", "/recovery")
|
||||||
// TEST
|
// TEST
|
||||||
assert.Equal(t, w.Code, 500)
|
assert.Equal(t, 500, w.Code)
|
||||||
assert.Contains(t, buffer.String(), "GET /recovery")
|
assert.Contains(t, buffer.String(), "GET /recovery")
|
||||||
assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
|
assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
|
||||||
assert.Contains(t, buffer.String(), "TestPanicInHandler")
|
assert.Contains(t, buffer.String(), "TestPanicInHandler")
|
||||||
@ -39,5 +39,5 @@ func TestPanicWithAbort(t *testing.T) {
|
|||||||
// RUN
|
// RUN
|
||||||
w := performRequest(router, "GET", "/recovery")
|
w := performRequest(router, "GET", "/recovery")
|
||||||
// TEST
|
// TEST
|
||||||
assert.Equal(t, w.Code, 400)
|
assert.Equal(t, 400, w.Code)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ package render
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -24,6 +26,9 @@ func TestRenderMsgPack(t *testing.T) {
|
|||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(MsgPack{data}).WriteContentType(w)
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "application/msgpack; charset=utf-8")
|
||||||
|
|
||||||
err := (MsgPack{data}).Render(w)
|
err := (MsgPack{data}).Render(w)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -45,6 +50,9 @@ func TestRenderJSON(t *testing.T) {
|
|||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(JSON{data}).WriteContentType(w)
|
||||||
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||||
|
|
||||||
err := (JSON{data}).Render(w)
|
err := (JSON{data}).Render(w)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -52,6 +60,14 @@ func TestRenderJSON(t *testing.T) {
|
|||||||
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderJSONPanics(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
data := make(chan int)
|
||||||
|
|
||||||
|
// json: unsupported type: chan int
|
||||||
|
assert.Panics(t, func() { (JSON{data}).Render(w) })
|
||||||
|
}
|
||||||
|
|
||||||
func TestRenderIndentedJSON(t *testing.T) {
|
func TestRenderIndentedJSON(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
@ -66,12 +82,24 @@ func TestRenderIndentedJSON(t *testing.T) {
|
|||||||
assert.Equal(t, w.Header().Get("Content-Type"), "application/json; charset=utf-8")
|
assert.Equal(t, w.Header().Get("Content-Type"), "application/json; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderIndentedJSONPanics(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
data := make(chan int)
|
||||||
|
|
||||||
|
// json: unsupported type: chan int
|
||||||
|
err := (IndentedJSON{data}).Render(w)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRenderSecureJSON(t *testing.T) {
|
func TestRenderSecureJSON(t *testing.T) {
|
||||||
w1 := httptest.NewRecorder()
|
w1 := httptest.NewRecorder()
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(SecureJSON{"while(1);", data}).WriteContentType(w1)
|
||||||
|
assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type"))
|
||||||
|
|
||||||
err1 := (SecureJSON{"while(1);", data}).Render(w1)
|
err1 := (SecureJSON{"while(1);", data}).Render(w1)
|
||||||
|
|
||||||
assert.NoError(t, err1)
|
assert.NoError(t, err1)
|
||||||
@ -91,6 +119,15 @@ func TestRenderSecureJSON(t *testing.T) {
|
|||||||
assert.Equal(t, "application/json; charset=utf-8", w2.Header().Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w2.Header().Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderSecureJSONFail(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
data := make(chan int)
|
||||||
|
|
||||||
|
// json: unsupported type: chan int
|
||||||
|
err := (SecureJSON{"while(1);", data}).Render(w)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
type xmlmap map[string]interface{}
|
type xmlmap map[string]interface{}
|
||||||
|
|
||||||
// Allows type H to be used with xml.Marshal
|
// Allows type H to be used with xml.Marshal
|
||||||
@ -111,10 +148,38 @@ func (h xmlmap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := e.EncodeToken(xml.EndElement{Name: start.Name}); err != nil {
|
|
||||||
return err
|
return e.EncodeToken(xml.EndElement{Name: start.Name})
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
func TestRenderYAML(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
data := `
|
||||||
|
a : Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
`
|
||||||
|
(YAML{data}).WriteContentType(w)
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "application/x-yaml; charset=utf-8")
|
||||||
|
|
||||||
|
err := (YAML{data}).Render(w)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, w.Body.String(), "\"\\na : Easy!\\nb:\\n\\tc: 2\\n\\td: [3, 4]\\n\\t\"\n")
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "application/x-yaml; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
type fail struct{}
|
||||||
|
|
||||||
|
// Hook MarshalYAML
|
||||||
|
func (ft *fail) MarshalYAML() (interface{}, error) {
|
||||||
|
return nil, errors.New("fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderYAMLFail(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
err := (YAML{&fail{}}).Render(w)
|
||||||
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderXML(t *testing.T) {
|
func TestRenderXML(t *testing.T) {
|
||||||
@ -123,6 +188,9 @@ func TestRenderXML(t *testing.T) {
|
|||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(XML{data}).WriteContentType(w)
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "application/xml; charset=utf-8")
|
||||||
|
|
||||||
err := (XML{data}).Render(w)
|
err := (XML{data}).Render(w)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -131,7 +199,30 @@ func TestRenderXML(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderRedirect(t *testing.T) {
|
func TestRenderRedirect(t *testing.T) {
|
||||||
// TODO
|
req, err := http.NewRequest("GET", "/test-redirect", nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data1 := Redirect{
|
||||||
|
Code: 301,
|
||||||
|
Request: req,
|
||||||
|
Location: "/new/location",
|
||||||
|
}
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
err = data1.Render(w)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data2 := Redirect{
|
||||||
|
Code: 200,
|
||||||
|
Request: req,
|
||||||
|
Location: "/new/location",
|
||||||
|
}
|
||||||
|
|
||||||
|
w = httptest.NewRecorder()
|
||||||
|
assert.Panics(t, func() { data2.Render(w) })
|
||||||
|
|
||||||
|
// only improve coverage
|
||||||
|
data2.WriteContentType(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderData(t *testing.T) {
|
func TestRenderData(t *testing.T) {
|
||||||
@ -151,6 +242,12 @@ func TestRenderData(t *testing.T) {
|
|||||||
func TestRenderString(t *testing.T) {
|
func TestRenderString(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
(String{
|
||||||
|
Format: "hello %s %d",
|
||||||
|
Data: []interface{}{},
|
||||||
|
}).WriteContentType(w)
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/plain; charset=utf-8")
|
||||||
|
|
||||||
err := (String{
|
err := (String{
|
||||||
Format: "hola %s %d",
|
Format: "hola %s %d",
|
||||||
Data: []interface{}{"manu", 2},
|
Data: []interface{}{"manu", 2},
|
||||||
@ -161,6 +258,19 @@ func TestRenderString(t *testing.T) {
|
|||||||
assert.Equal(t, w.Header().Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/plain; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderStringLenZero(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
err := (String{
|
||||||
|
Format: "hola %s %d",
|
||||||
|
Data: []interface{}{},
|
||||||
|
}).Render(w)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, w.Body.String(), "hola %s %d")
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/plain; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRenderHTMLTemplate(t *testing.T) {
|
func TestRenderHTMLTemplate(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
||||||
@ -176,3 +286,64 @@ func TestRenderHTMLTemplate(t *testing.T) {
|
|||||||
assert.Equal(t, w.Body.String(), "Hello alexandernyquist")
|
assert.Equal(t, w.Body.String(), "Hello alexandernyquist")
|
||||||
assert.Equal(t, w.Header().Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderHTMLTemplateEmptyName(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
templ := template.Must(template.New("").Parse(`Hello {{.name}}`))
|
||||||
|
|
||||||
|
htmlRender := HTMLProduction{Template: templ}
|
||||||
|
instance := htmlRender.Instance("", map[string]interface{}{
|
||||||
|
"name": "alexandernyquist",
|
||||||
|
})
|
||||||
|
|
||||||
|
err := instance.Render(w)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, w.Body.String(), "Hello alexandernyquist")
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderHTMLDebugFiles(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
htmlRender := HTMLDebug{Files: []string{"../fixtures/basic/hello.tmpl"},
|
||||||
|
Glob: "",
|
||||||
|
Delims: Delims{Left: "{[{", Right: "}]}"},
|
||||||
|
FuncMap: nil,
|
||||||
|
}
|
||||||
|
instance := htmlRender.Instance("hello.tmpl", map[string]interface{}{
|
||||||
|
"name": "thinkerou",
|
||||||
|
})
|
||||||
|
|
||||||
|
err := instance.Render(w)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, w.Body.String(), "<h1>Hello thinkerou</h1>")
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderHTMLDebugGlob(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
htmlRender := HTMLDebug{Files: nil,
|
||||||
|
Glob: "../fixtures/basic/hello*",
|
||||||
|
Delims: Delims{Left: "{[{", Right: "}]}"},
|
||||||
|
FuncMap: nil,
|
||||||
|
}
|
||||||
|
instance := htmlRender.Instance("hello.tmpl", map[string]interface{}{
|
||||||
|
"name": "thinkerou",
|
||||||
|
})
|
||||||
|
|
||||||
|
err := instance.Render(w)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, w.Body.String(), "<h1>Hello thinkerou</h1>")
|
||||||
|
assert.Equal(t, w.Header().Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderHTMLDebugPanics(t *testing.T) {
|
||||||
|
htmlRender := HTMLDebug{Files: nil,
|
||||||
|
Glob: "",
|
||||||
|
Delims: Delims{"{{", "}}"},
|
||||||
|
FuncMap: nil,
|
||||||
|
}
|
||||||
|
assert.Panics(t, func() { htmlRender.Instance("", nil) })
|
||||||
|
}
|
||||||
|
@ -20,15 +20,15 @@ func TestRouterGroupBasic(t *testing.T) {
|
|||||||
group.Use(func(c *Context) {})
|
group.Use(func(c *Context) {})
|
||||||
|
|
||||||
assert.Len(t, group.Handlers, 2)
|
assert.Len(t, group.Handlers, 2)
|
||||||
assert.Equal(t, group.BasePath(), "/hola")
|
assert.Equal(t, "/hola", group.BasePath())
|
||||||
assert.Equal(t, group.engine, router)
|
assert.Equal(t, router, group.engine)
|
||||||
|
|
||||||
group2 := group.Group("manu")
|
group2 := group.Group("manu")
|
||||||
group2.Use(func(c *Context) {}, func(c *Context) {})
|
group2.Use(func(c *Context) {}, func(c *Context) {})
|
||||||
|
|
||||||
assert.Len(t, group2.Handlers, 4)
|
assert.Len(t, group2.Handlers, 4)
|
||||||
assert.Equal(t, group2.BasePath(), "/hola/manu")
|
assert.Equal(t, "/hola/manu", group2.BasePath())
|
||||||
assert.Equal(t, group2.engine, router)
|
assert.Equal(t, router, group2.engine)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterGroupBasicHandle(t *testing.T) {
|
func TestRouterGroupBasicHandle(t *testing.T) {
|
||||||
@ -44,10 +44,10 @@ func TestRouterGroupBasicHandle(t *testing.T) {
|
|||||||
func performRequestInGroup(t *testing.T, method string) {
|
func performRequestInGroup(t *testing.T, method string) {
|
||||||
router := New()
|
router := New()
|
||||||
v1 := router.Group("v1", func(c *Context) {})
|
v1 := router.Group("v1", func(c *Context) {})
|
||||||
assert.Equal(t, v1.BasePath(), "/v1")
|
assert.Equal(t, "/v1", v1.BasePath())
|
||||||
|
|
||||||
login := v1.Group("/login/", func(c *Context) {}, func(c *Context) {})
|
login := v1.Group("/login/", func(c *Context) {}, func(c *Context) {})
|
||||||
assert.Equal(t, login.BasePath(), "/v1/login/")
|
assert.Equal(t, "/v1/login/", login.BasePath())
|
||||||
|
|
||||||
handler := func(c *Context) {
|
handler := func(c *Context) {
|
||||||
c.String(400, "the method was %s and index %d", c.Request.Method, c.index)
|
c.String(400, "the method was %s and index %d", c.Request.Method, c.index)
|
||||||
@ -80,12 +80,12 @@ func performRequestInGroup(t *testing.T, method string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w := performRequest(router, method, "/v1/login/test")
|
w := performRequest(router, method, "/v1/login/test")
|
||||||
assert.Equal(t, w.Code, 400)
|
assert.Equal(t, 400, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "the method was "+method+" and index 3")
|
assert.Equal(t, "the method was "+method+" and index 3", w.Body.String())
|
||||||
|
|
||||||
w = performRequest(router, method, "/v1/test")
|
w = performRequest(router, method, "/v1/test")
|
||||||
assert.Equal(t, w.Code, 400)
|
assert.Equal(t, 400, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "the method was "+method+" and index 1")
|
assert.Equal(t, "the method was "+method+" and index 1", w.Body.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterGroupInvalidStatic(t *testing.T) {
|
func TestRouterGroupInvalidStatic(t *testing.T) {
|
||||||
|
124
routes_test.go
124
routes_test.go
@ -36,7 +36,7 @@ func testRouteOK(method string, t *testing.T) {
|
|||||||
|
|
||||||
w := performRequest(r, method, "/test")
|
w := performRequest(r, method, "/test")
|
||||||
assert.True(t, passed)
|
assert.True(t, passed)
|
||||||
assert.Equal(t, w.Code, http.StatusOK)
|
assert.Equal(t, http.StatusOK, w.Code)
|
||||||
|
|
||||||
performRequest(r, method, "/test2")
|
performRequest(r, method, "/test2")
|
||||||
assert.True(t, passedAny)
|
assert.True(t, passedAny)
|
||||||
@ -53,7 +53,7 @@ func testRouteNotOK(method string, t *testing.T) {
|
|||||||
w := performRequest(router, method, "/test")
|
w := performRequest(router, method, "/test")
|
||||||
|
|
||||||
assert.False(t, passed)
|
assert.False(t, passed)
|
||||||
assert.Equal(t, w.Code, http.StatusNotFound)
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSingleRouteOK tests that POST route is correctly invoked.
|
// TestSingleRouteOK tests that POST route is correctly invoked.
|
||||||
@ -74,7 +74,7 @@ func testRouteNotOK2(method string, t *testing.T) {
|
|||||||
w := performRequest(router, method, "/test")
|
w := performRequest(router, method, "/test")
|
||||||
|
|
||||||
assert.False(t, passed)
|
assert.False(t, passed)
|
||||||
assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
|
assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterMethod(t *testing.T) {
|
func TestRouterMethod(t *testing.T) {
|
||||||
@ -93,8 +93,8 @@ func TestRouterMethod(t *testing.T) {
|
|||||||
|
|
||||||
w := performRequest(router, "PUT", "/hey")
|
w := performRequest(router, "PUT", "/hey")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "called")
|
assert.Equal(t, "called", w.Body.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterGroupRouteOK(t *testing.T) {
|
func TestRouterGroupRouteOK(t *testing.T) {
|
||||||
@ -143,43 +143,43 @@ func TestRouteRedirectTrailingSlash(t *testing.T) {
|
|||||||
router.PUT("/path4/", func(c *Context) {})
|
router.PUT("/path4/", func(c *Context) {})
|
||||||
|
|
||||||
w := performRequest(router, "GET", "/path/")
|
w := performRequest(router, "GET", "/path/")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/path")
|
assert.Equal(t, "/path", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 301)
|
assert.Equal(t, 301, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "GET", "/path2")
|
w = performRequest(router, "GET", "/path2")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/path2/")
|
assert.Equal(t, "/path2/", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 301)
|
assert.Equal(t, 301, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "POST", "/path3/")
|
w = performRequest(router, "POST", "/path3/")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/path3")
|
assert.Equal(t, "/path3", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 307)
|
assert.Equal(t, 307, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "PUT", "/path4")
|
w = performRequest(router, "PUT", "/path4")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/path4/")
|
assert.Equal(t, "/path4/", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 307)
|
assert.Equal(t, 307, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "GET", "/path")
|
w = performRequest(router, "GET", "/path")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "GET", "/path2/")
|
w = performRequest(router, "GET", "/path2/")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "POST", "/path3")
|
w = performRequest(router, "POST", "/path3")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "PUT", "/path4/")
|
w = performRequest(router, "PUT", "/path4/")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
|
|
||||||
router.RedirectTrailingSlash = false
|
router.RedirectTrailingSlash = false
|
||||||
|
|
||||||
w = performRequest(router, "GET", "/path/")
|
w = performRequest(router, "GET", "/path/")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
w = performRequest(router, "GET", "/path2")
|
w = performRequest(router, "GET", "/path2")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
w = performRequest(router, "POST", "/path3/")
|
w = performRequest(router, "POST", "/path3/")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
w = performRequest(router, "PUT", "/path4")
|
w = performRequest(router, "PUT", "/path4")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteRedirectFixedPath(t *testing.T) {
|
func TestRouteRedirectFixedPath(t *testing.T) {
|
||||||
@ -193,20 +193,20 @@ func TestRouteRedirectFixedPath(t *testing.T) {
|
|||||||
router.POST("/Path4/", func(c *Context) {})
|
router.POST("/Path4/", func(c *Context) {})
|
||||||
|
|
||||||
w := performRequest(router, "GET", "/PATH")
|
w := performRequest(router, "GET", "/PATH")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/path")
|
assert.Equal(t, "/path", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 301)
|
assert.Equal(t, 301, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "GET", "/path2")
|
w = performRequest(router, "GET", "/path2")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/Path2")
|
assert.Equal(t, "/Path2", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 301)
|
assert.Equal(t, 301, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "POST", "/path3")
|
w = performRequest(router, "POST", "/path3")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/PATH3")
|
assert.Equal(t, "/PATH3", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 307)
|
assert.Equal(t, 307, w.Code)
|
||||||
|
|
||||||
w = performRequest(router, "POST", "/path4")
|
w = performRequest(router, "POST", "/path4")
|
||||||
assert.Equal(t, w.Header().Get("Location"), "/Path4/")
|
assert.Equal(t, "/Path4/", w.Header().Get("Location"))
|
||||||
assert.Equal(t, w.Code, 307)
|
assert.Equal(t, 307, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestContextParamsGet tests that a parameter can be parsed from the URL.
|
// TestContextParamsGet tests that a parameter can be parsed from the URL.
|
||||||
@ -236,10 +236,10 @@ func TestRouteParamsByName(t *testing.T) {
|
|||||||
|
|
||||||
w := performRequest(router, "GET", "/test/john/smith/is/super/great")
|
w := performRequest(router, "GET", "/test/john/smith/is/super/great")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
assert.Equal(t, name, "john")
|
assert.Equal(t, "john", name)
|
||||||
assert.Equal(t, lastName, "smith")
|
assert.Equal(t, "smith", lastName)
|
||||||
assert.Equal(t, wild, "/is/super/great")
|
assert.Equal(t, "/is/super/great", wild)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestHandleStaticFile - ensure the static file handles properly
|
// TestHandleStaticFile - ensure the static file handles properly
|
||||||
@ -265,15 +265,15 @@ func TestRouteStaticFile(t *testing.T) {
|
|||||||
w2 := performRequest(router, "GET", "/result")
|
w2 := performRequest(router, "GET", "/result")
|
||||||
|
|
||||||
assert.Equal(t, w, w2)
|
assert.Equal(t, w, w2)
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "Gin Web Framework")
|
assert.Equal(t, "Gin Web Framework", w.Body.String())
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, "text/plain; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
|
|
||||||
w3 := performRequest(router, "HEAD", "/using_static/"+filename)
|
w3 := performRequest(router, "HEAD", "/using_static/"+filename)
|
||||||
w4 := performRequest(router, "HEAD", "/result")
|
w4 := performRequest(router, "HEAD", "/result")
|
||||||
|
|
||||||
assert.Equal(t, w3, w4)
|
assert.Equal(t, w3, w4)
|
||||||
assert.Equal(t, w3.Code, 200)
|
assert.Equal(t, 200, w3.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestHandleStaticDir - ensure the root/sub dir handles properly
|
// TestHandleStaticDir - ensure the root/sub dir handles properly
|
||||||
@ -283,9 +283,9 @@ func TestRouteStaticListingDir(t *testing.T) {
|
|||||||
|
|
||||||
w := performRequest(router, "GET", "/")
|
w := performRequest(router, "GET", "/")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
assert.Contains(t, w.Body.String(), "gin.go")
|
assert.Contains(t, w.Body.String(), "gin.go")
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestHandleHeadToDir - ensure the root/sub dir handles properly
|
// TestHandleHeadToDir - ensure the root/sub dir handles properly
|
||||||
@ -295,7 +295,7 @@ func TestRouteStaticNoListing(t *testing.T) {
|
|||||||
|
|
||||||
w := performRequest(router, "GET", "/")
|
w := performRequest(router, "GET", "/")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
assert.NotContains(t, w.Body.String(), "gin.go")
|
assert.NotContains(t, w.Body.String(), "gin.go")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,12 +310,12 @@ func TestRouterMiddlewareAndStatic(t *testing.T) {
|
|||||||
|
|
||||||
w := performRequest(router, "GET", "/gin.go")
|
w := performRequest(router, "GET", "/gin.go")
|
||||||
|
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
assert.Contains(t, w.Body.String(), "package gin")
|
assert.Contains(t, w.Body.String(), "package gin")
|
||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, "text/plain; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
assert.NotEqual(t, w.HeaderMap.Get("Last-Modified"), "Mon, 02 Jan 2006 15:04:05 MST")
|
assert.NotEqual(t, w.HeaderMap.Get("Last-Modified"), "Mon, 02 Jan 2006 15:04:05 MST")
|
||||||
assert.Equal(t, w.HeaderMap.Get("Expires"), "Mon, 02 Jan 2006 15:04:05 MST")
|
assert.Equal(t, "Mon, 02 Jan 2006 15:04:05 MST", w.HeaderMap.Get("Expires"))
|
||||||
assert.Equal(t, w.HeaderMap.Get("x-GIN"), "Gin Framework")
|
assert.Equal(t, "Gin Framework", w.HeaderMap.Get("x-GIN"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteNotAllowedEnabled(t *testing.T) {
|
func TestRouteNotAllowedEnabled(t *testing.T) {
|
||||||
@ -323,14 +323,14 @@ func TestRouteNotAllowedEnabled(t *testing.T) {
|
|||||||
router.HandleMethodNotAllowed = true
|
router.HandleMethodNotAllowed = true
|
||||||
router.POST("/path", func(c *Context) {})
|
router.POST("/path", func(c *Context) {})
|
||||||
w := performRequest(router, "GET", "/path")
|
w := performRequest(router, "GET", "/path")
|
||||||
assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
|
assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
|
||||||
|
|
||||||
router.NoMethod(func(c *Context) {
|
router.NoMethod(func(c *Context) {
|
||||||
c.String(http.StatusTeapot, "responseText")
|
c.String(http.StatusTeapot, "responseText")
|
||||||
})
|
})
|
||||||
w = performRequest(router, "GET", "/path")
|
w = performRequest(router, "GET", "/path")
|
||||||
assert.Equal(t, w.Body.String(), "responseText")
|
assert.Equal(t, "responseText", w.Body.String())
|
||||||
assert.Equal(t, w.Code, http.StatusTeapot)
|
assert.Equal(t, http.StatusTeapot, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteNotAllowedDisabled(t *testing.T) {
|
func TestRouteNotAllowedDisabled(t *testing.T) {
|
||||||
@ -338,14 +338,14 @@ func TestRouteNotAllowedDisabled(t *testing.T) {
|
|||||||
router.HandleMethodNotAllowed = false
|
router.HandleMethodNotAllowed = false
|
||||||
router.POST("/path", func(c *Context) {})
|
router.POST("/path", func(c *Context) {})
|
||||||
w := performRequest(router, "GET", "/path")
|
w := performRequest(router, "GET", "/path")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
|
|
||||||
router.NoMethod(func(c *Context) {
|
router.NoMethod(func(c *Context) {
|
||||||
c.String(http.StatusTeapot, "responseText")
|
c.String(http.StatusTeapot, "responseText")
|
||||||
})
|
})
|
||||||
w = performRequest(router, "GET", "/path")
|
w = performRequest(router, "GET", "/path")
|
||||||
assert.Equal(t, w.Body.String(), "404 page not found")
|
assert.Equal(t, "404 page not found", w.Body.String())
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterNotFound(t *testing.T) {
|
func TestRouterNotFound(t *testing.T) {
|
||||||
@ -372,9 +372,9 @@ func TestRouterNotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tr := range testRoutes {
|
for _, tr := range testRoutes {
|
||||||
w := performRequest(router, "GET", tr.route)
|
w := performRequest(router, "GET", tr.route)
|
||||||
assert.Equal(t, w.Code, tr.code)
|
assert.Equal(t, tr.code, w.Code)
|
||||||
if w.Code != 404 {
|
if w.Code != 404 {
|
||||||
assert.Equal(t, fmt.Sprint(w.Header().Get("Location")), tr.location)
|
assert.Equal(t, tr.location, fmt.Sprint(w.Header().Get("Location")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,20 +385,20 @@ func TestRouterNotFound(t *testing.T) {
|
|||||||
notFound = true
|
notFound = true
|
||||||
})
|
})
|
||||||
w := performRequest(router, "GET", "/nope")
|
w := performRequest(router, "GET", "/nope")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
assert.True(t, notFound)
|
assert.True(t, notFound)
|
||||||
|
|
||||||
// Test other method than GET (want 307 instead of 301)
|
// Test other method than GET (want 307 instead of 301)
|
||||||
router.PATCH("/path", func(c *Context) {})
|
router.PATCH("/path", func(c *Context) {})
|
||||||
w = performRequest(router, "PATCH", "/path/")
|
w = performRequest(router, "PATCH", "/path/")
|
||||||
assert.Equal(t, w.Code, 307)
|
assert.Equal(t, 307, w.Code)
|
||||||
assert.Equal(t, fmt.Sprint(w.Header()), "map[Location:[/path]]")
|
assert.Equal(t, "map[Location:[/path]]", fmt.Sprint(w.Header()))
|
||||||
|
|
||||||
// Test special case where no node for the prefix "/" exists
|
// Test special case where no node for the prefix "/" exists
|
||||||
router = New()
|
router = New()
|
||||||
router.GET("/a", func(c *Context) {})
|
router.GET("/a", func(c *Context) {})
|
||||||
w = performRequest(router, "GET", "/")
|
w = performRequest(router, "GET", "/")
|
||||||
assert.Equal(t, w.Code, 404)
|
assert.Equal(t, 404, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteRawPath(t *testing.T) {
|
func TestRouteRawPath(t *testing.T) {
|
||||||
@ -409,15 +409,15 @@ func TestRouteRawPath(t *testing.T) {
|
|||||||
name := c.Params.ByName("name")
|
name := c.Params.ByName("name")
|
||||||
num := c.Params.ByName("num")
|
num := c.Params.ByName("num")
|
||||||
|
|
||||||
assert.Equal(t, c.Param("name"), name)
|
assert.Equal(t, name, c.Param("name"))
|
||||||
assert.Equal(t, c.Param("num"), num)
|
assert.Equal(t, num, c.Param("num"))
|
||||||
|
|
||||||
assert.Equal(t, "Some/Other/Project", name)
|
assert.Equal(t, "Some/Other/Project", name)
|
||||||
assert.Equal(t, "222", num)
|
assert.Equal(t, "222", num)
|
||||||
})
|
})
|
||||||
|
|
||||||
w := performRequest(route, "POST", "/project/Some%2FOther%2FProject/build/222")
|
w := performRequest(route, "POST", "/project/Some%2FOther%2FProject/build/222")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteRawPathNoUnescape(t *testing.T) {
|
func TestRouteRawPathNoUnescape(t *testing.T) {
|
||||||
@ -429,15 +429,15 @@ func TestRouteRawPathNoUnescape(t *testing.T) {
|
|||||||
name := c.Params.ByName("name")
|
name := c.Params.ByName("name")
|
||||||
num := c.Params.ByName("num")
|
num := c.Params.ByName("num")
|
||||||
|
|
||||||
assert.Equal(t, c.Param("name"), name)
|
assert.Equal(t, name, c.Param("name"))
|
||||||
assert.Equal(t, c.Param("num"), num)
|
assert.Equal(t, num, c.Param("num"))
|
||||||
|
|
||||||
assert.Equal(t, "Some%2FOther%2FProject", name)
|
assert.Equal(t, "Some%2FOther%2FProject", name)
|
||||||
assert.Equal(t, "333", num)
|
assert.Equal(t, "333", num)
|
||||||
})
|
})
|
||||||
|
|
||||||
w := performRequest(route, "POST", "/project/Some%2FOther%2FProject/build/333")
|
w := performRequest(route, "POST", "/project/Some%2FOther%2FProject/build/333")
|
||||||
assert.Equal(t, w.Code, 200)
|
assert.Equal(t, 200, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteServeErrorWithWriteHeader(t *testing.T) {
|
func TestRouteServeErrorWithWriteHeader(t *testing.T) {
|
||||||
|
14
tree.go
14
tree.go
@ -87,13 +87,13 @@ const (
|
|||||||
|
|
||||||
type node struct {
|
type node struct {
|
||||||
path string
|
path string
|
||||||
wildChild bool
|
|
||||||
nType nodeType
|
|
||||||
maxParams uint8
|
|
||||||
indices string
|
indices string
|
||||||
children []*node
|
children []*node
|
||||||
handlers HandlersChain
|
handlers HandlersChain
|
||||||
priority uint32
|
priority uint32
|
||||||
|
nType nodeType
|
||||||
|
maxParams uint8
|
||||||
|
wildChild bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// increments priority of the given child and reorders if necessary.
|
// increments priority of the given child and reorders if necessary.
|
||||||
@ -384,7 +384,7 @@ walk: // Outer loop for walking the tree
|
|||||||
// Nothing found.
|
// Nothing found.
|
||||||
// We can recommend to redirect to the same URL without a
|
// We can recommend to redirect to the same URL without a
|
||||||
// trailing slash if a leaf exists for that path.
|
// trailing slash if a leaf exists for that path.
|
||||||
tsr = (path == "/" && n.handlers != nil)
|
tsr = path == "/" && n.handlers != nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ walk: // Outer loop for walking the tree
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ... but we can't
|
// ... but we can't
|
||||||
tsr = (len(path) == end+1)
|
tsr = len(path) == end+1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +435,7 @@ walk: // Outer loop for walking the tree
|
|||||||
// No handle found. Check if a handle for this path + a
|
// No handle found. Check if a handle for this path + a
|
||||||
// trailing slash exists for TSR recommendation
|
// trailing slash exists for TSR recommendation
|
||||||
n = n.children[0]
|
n = n.children[0]
|
||||||
tsr = (n.path == "/" && n.handlers != nil)
|
tsr = n.path == "/" && n.handlers != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -530,7 +530,7 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
|
|||||||
|
|
||||||
// Nothing found. We can recommend to redirect to the same URL
|
// Nothing found. We can recommend to redirect to the same URL
|
||||||
// without a trailing slash if a leaf exists for that path
|
// without a trailing slash if a leaf exists for that path
|
||||||
found = (fixTrailingSlash && path == "/" && n.handlers != nil)
|
found = fixTrailingSlash && path == "/" && n.handlers != nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
tree_test.go
11
tree_test.go
@ -5,22 +5,11 @@
|
|||||||
package gin
|
package gin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printChildren(n *node, prefix string) {
|
|
||||||
fmt.Printf(" %02d:%02d %s%s[%d] %v %t %d \r\n", n.priority, n.maxParams, prefix, n.path, len(n.children), n.handlers, n.wildChild, n.nType)
|
|
||||||
for l := len(n.path); l > 0; l-- {
|
|
||||||
prefix += " "
|
|
||||||
}
|
|
||||||
for _, child := range n.children {
|
|
||||||
printChildren(child, prefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
var fakeHandlerValue string
|
var fakeHandlerValue string
|
||||||
|
|
||||||
|
11
utils.go
11
utils.go
@ -33,18 +33,23 @@ func Bind(val interface{}) HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WrapF is a helper function for wrapping http.HandlerFunc
|
||||||
|
// Returns a Gin middleware
|
||||||
func WrapF(f http.HandlerFunc) HandlerFunc {
|
func WrapF(f http.HandlerFunc) HandlerFunc {
|
||||||
return func(c *Context) {
|
return func(c *Context) {
|
||||||
f(c.Writer, c.Request)
|
f(c.Writer, c.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WrapH is a helper function for wrapping http.Handler
|
||||||
|
// Returns a Gin middleware
|
||||||
func WrapH(h http.Handler) HandlerFunc {
|
func WrapH(h http.Handler) HandlerFunc {
|
||||||
return func(c *Context) {
|
return func(c *Context) {
|
||||||
h.ServeHTTP(c.Writer, c.Request)
|
h.ServeHTTP(c.Writer, c.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// H is a shortcup for map[string]interface{}
|
||||||
type H map[string]interface{}
|
type H map[string]interface{}
|
||||||
|
|
||||||
// MarshalXML allows type H to be used with xml.Marshal.
|
// MarshalXML allows type H to be used with xml.Marshal.
|
||||||
@ -65,10 +70,8 @@ func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := e.EncodeToken(xml.EndElement{Name: start.Name}); err != nil {
|
|
||||||
return err
|
return e.EncodeToken(xml.EndElement{Name: start.Name})
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func assert1(guard bool, text string) {
|
func assert1(guard bool, text string) {
|
||||||
|
@ -21,8 +21,8 @@ type testStruct struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *testStruct) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (t *testStruct) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
assert.Equal(t.T, req.Method, "POST")
|
assert.Equal(t.T, "POST", req.Method)
|
||||||
assert.Equal(t.T, req.URL.Path, "/path")
|
assert.Equal(t.T, "/path", req.URL.Path)
|
||||||
w.WriteHeader(500)
|
w.WriteHeader(500)
|
||||||
fmt.Fprint(w, "hello")
|
fmt.Fprint(w, "hello")
|
||||||
}
|
}
|
||||||
@ -31,50 +31,50 @@ func TestWrap(t *testing.T) {
|
|||||||
router := New()
|
router := New()
|
||||||
router.POST("/path", WrapH(&testStruct{t}))
|
router.POST("/path", WrapH(&testStruct{t}))
|
||||||
router.GET("/path2", WrapF(func(w http.ResponseWriter, req *http.Request) {
|
router.GET("/path2", WrapF(func(w http.ResponseWriter, req *http.Request) {
|
||||||
assert.Equal(t, req.Method, "GET")
|
assert.Equal(t, "GET", req.Method)
|
||||||
assert.Equal(t, req.URL.Path, "/path2")
|
assert.Equal(t, "/path2", req.URL.Path)
|
||||||
w.WriteHeader(400)
|
w.WriteHeader(400)
|
||||||
fmt.Fprint(w, "hola!")
|
fmt.Fprint(w, "hola!")
|
||||||
}))
|
}))
|
||||||
|
|
||||||
w := performRequest(router, "POST", "/path")
|
w := performRequest(router, "POST", "/path")
|
||||||
assert.Equal(t, w.Code, 500)
|
assert.Equal(t, 500, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "hello")
|
assert.Equal(t, "hello", w.Body.String())
|
||||||
|
|
||||||
w = performRequest(router, "GET", "/path2")
|
w = performRequest(router, "GET", "/path2")
|
||||||
assert.Equal(t, w.Code, 400)
|
assert.Equal(t, 400, w.Code)
|
||||||
assert.Equal(t, w.Body.String(), "hola!")
|
assert.Equal(t, "hola!", w.Body.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLastChar(t *testing.T) {
|
func TestLastChar(t *testing.T) {
|
||||||
assert.Equal(t, lastChar("hola"), uint8('a'))
|
assert.Equal(t, uint8('a'), lastChar("hola"))
|
||||||
assert.Equal(t, lastChar("adios"), uint8('s'))
|
assert.Equal(t, uint8('s'), lastChar("adios"))
|
||||||
assert.Panics(t, func() { lastChar("") })
|
assert.Panics(t, func() { lastChar("") })
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseAccept(t *testing.T) {
|
func TestParseAccept(t *testing.T) {
|
||||||
parts := parseAccept("text/html , application/xhtml+xml,application/xml;q=0.9, */* ;q=0.8")
|
parts := parseAccept("text/html , application/xhtml+xml,application/xml;q=0.9, */* ;q=0.8")
|
||||||
assert.Len(t, parts, 4)
|
assert.Len(t, parts, 4)
|
||||||
assert.Equal(t, parts[0], "text/html")
|
assert.Equal(t, "text/html", parts[0])
|
||||||
assert.Equal(t, parts[1], "application/xhtml+xml")
|
assert.Equal(t, "application/xhtml+xml", parts[1])
|
||||||
assert.Equal(t, parts[2], "application/xml")
|
assert.Equal(t, "application/xml", parts[2])
|
||||||
assert.Equal(t, parts[3], "*/*")
|
assert.Equal(t, "*/*", parts[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChooseData(t *testing.T) {
|
func TestChooseData(t *testing.T) {
|
||||||
A := "a"
|
A := "a"
|
||||||
B := "b"
|
B := "b"
|
||||||
assert.Equal(t, chooseData(A, B), A)
|
assert.Equal(t, A, chooseData(A, B))
|
||||||
assert.Equal(t, chooseData(nil, B), B)
|
assert.Equal(t, B, chooseData(nil, B))
|
||||||
assert.Panics(t, func() { chooseData(nil, nil) })
|
assert.Panics(t, func() { chooseData(nil, nil) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterFlags(t *testing.T) {
|
func TestFilterFlags(t *testing.T) {
|
||||||
result := filterFlags("text/html ")
|
result := filterFlags("text/html ")
|
||||||
assert.Equal(t, result, "text/html")
|
assert.Equal(t, "text/html", result)
|
||||||
|
|
||||||
result = filterFlags("text/html;")
|
result = filterFlags("text/html;")
|
||||||
assert.Equal(t, result, "text/html")
|
assert.Equal(t, "text/html", result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFunctionName(t *testing.T) {
|
func TestFunctionName(t *testing.T) {
|
||||||
@ -86,16 +86,16 @@ func somefunction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestJoinPaths(t *testing.T) {
|
func TestJoinPaths(t *testing.T) {
|
||||||
assert.Equal(t, joinPaths("", ""), "")
|
assert.Equal(t, "", joinPaths("", ""))
|
||||||
assert.Equal(t, joinPaths("", "/"), "/")
|
assert.Equal(t, "/", joinPaths("", "/"))
|
||||||
assert.Equal(t, joinPaths("/a", ""), "/a")
|
assert.Equal(t, "/a", joinPaths("/a", ""))
|
||||||
assert.Equal(t, joinPaths("/a/", ""), "/a/")
|
assert.Equal(t, "/a/", joinPaths("/a/", ""))
|
||||||
assert.Equal(t, joinPaths("/a/", "/"), "/a/")
|
assert.Equal(t, "/a/", joinPaths("/a/", "/"))
|
||||||
assert.Equal(t, joinPaths("/a", "/"), "/a/")
|
assert.Equal(t, "/a/", joinPaths("/a", "/"))
|
||||||
assert.Equal(t, joinPaths("/a", "/hola"), "/a/hola")
|
assert.Equal(t, "/a/hola", joinPaths("/a", "/hola"))
|
||||||
assert.Equal(t, joinPaths("/a/", "/hola"), "/a/hola")
|
assert.Equal(t, "/a/hola", joinPaths("/a/", "/hola"))
|
||||||
assert.Equal(t, joinPaths("/a/", "/hola/"), "/a/hola/")
|
assert.Equal(t, "/a/hola/", joinPaths("/a/", "/hola/"))
|
||||||
assert.Equal(t, joinPaths("/a/", "/hola//"), "/a/hola/")
|
assert.Equal(t, "/a/hola/", joinPaths("/a/", "/hola//"))
|
||||||
}
|
}
|
||||||
|
|
||||||
type bindTestStruct struct {
|
type bindTestStruct struct {
|
||||||
@ -113,8 +113,8 @@ func TestBindMiddleware(t *testing.T) {
|
|||||||
})
|
})
|
||||||
performRequest(router, "GET", "/?foo=hola&bar=10")
|
performRequest(router, "GET", "/?foo=hola&bar=10")
|
||||||
assert.True(t, called)
|
assert.True(t, called)
|
||||||
assert.Equal(t, value.Foo, "hola")
|
assert.Equal(t, "hola", value.Foo)
|
||||||
assert.Equal(t, value.Bar, 10)
|
assert.Equal(t, 10, value.Bar)
|
||||||
|
|
||||||
called = false
|
called = false
|
||||||
performRequest(router, "GET", "/?foo=hola&bar=1")
|
performRequest(router, "GET", "/?foo=hola&bar=1")
|
||||||
|
18
vendor/vendor.json
vendored
18
vendor/vendor.json
vendored
@ -22,10 +22,10 @@
|
|||||||
"revisionTime": "2017-01-09T09:34:21Z"
|
"revisionTime": "2017-01-09T09:34:21Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "FJKrZuFmeLJp8HDeJc6UkIDBPUw=",
|
"checksumSHA1": "+vZNyF2MykVjenLg1TpjjgjthV0=",
|
||||||
"path": "github.com/gin-gonic/autotls",
|
"path": "github.com/gin-gonic/autotls",
|
||||||
"revision": "5b3297bdcee778ff3bbdc99ab7c41e1c2677d22d",
|
"revision": "8ca25fbde72bb72a00466215b94b489c71fcb815",
|
||||||
"revisionTime": "2017-04-16T09:39:34Z"
|
"revisionTime": "2017-09-16T16:54:15Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "qlPUeFabwF4RKAOF1H+yBFU1Veg=",
|
"checksumSHA1": "qlPUeFabwF4RKAOF1H+yBFU1Veg=",
|
||||||
@ -65,6 +65,12 @@
|
|||||||
"revision": "976c720a22c8eb4eb6a0b4348ad85ad12491a506",
|
"revision": "976c720a22c8eb4eb6a0b4348ad85ad12491a506",
|
||||||
"revisionTime": "2016-09-25T22:06:09Z"
|
"revisionTime": "2016-09-25T22:06:09Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "IopMW+arBezL5bqOfrVU6UEfn28=",
|
||||||
|
"path": "github.com/thinkerou/favicon",
|
||||||
|
"revision": "94a442a49da6e2d44bdd5e0d2e2e185c43a19d93",
|
||||||
|
"revisionTime": "2017-07-10T14:05:20Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "CoxdaTYdPZNJXr8mJfLxye428N0=",
|
"checksumSHA1": "CoxdaTYdPZNJXr8mJfLxye428N0=",
|
||||||
"path": "github.com/ugorji/go/codec",
|
"path": "github.com/ugorji/go/codec",
|
||||||
@ -90,6 +96,12 @@
|
|||||||
"revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a",
|
"revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a",
|
||||||
"revisionTime": "2016-10-18T08:54:36Z"
|
"revisionTime": "2016-10-18T08:54:36Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "S0DP7Pn7sZUmXc55IzZnNvERu6s=",
|
||||||
|
"path": "golang.org/x/sync/errgroup",
|
||||||
|
"revision": "8e0aa688b654ef28caa72506fa5ec8dba9fc7690",
|
||||||
|
"revisionTime": "2017-07-19T03:38:01Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "TVEkpH3gq84iQ39I4R+mlDwjuVI=",
|
"checksumSHA1": "TVEkpH3gq84iQ39I4R+mlDwjuVI=",
|
||||||
"path": "golang.org/x/sys/unix",
|
"path": "golang.org/x/sys/unix",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user