mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-24 02:32:17 +08:00
Merge branch 'master' into add-test
This commit is contained in:
commit
cba8682666
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ GOFMT ?= gofmt "-s"
|
||||
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||
GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*")
|
||||
|
||||
all: build
|
||||
all: install
|
||||
|
||||
install: deps
|
||||
govendor sync
|
||||
|
10
README.md
10
README.md
@ -117,7 +117,7 @@ $ go get github.com/kardianos/govendor
|
||||
2. Create your project folder and `cd` inside
|
||||
|
||||
```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
|
||||
@ -385,7 +385,7 @@ func main() {
|
||||
r := gin.New()
|
||||
|
||||
// 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
|
||||
r.Use(gin.Logger())
|
||||
|
||||
@ -435,7 +435,7 @@ func main() {
|
||||
c.String(200, "pong")
|
||||
})
|
||||
|
||||
r.Run(":8080")
|
||||
router.Run(":8080")
|
||||
}
|
||||
```
|
||||
|
||||
@ -1071,7 +1071,7 @@ func main() {
|
||||
|
||||
### 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
|
||||
func main() {
|
||||
@ -1190,7 +1190,7 @@ func main() {
|
||||
|
||||
### 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)
|
||||
```go
|
||||
|
12
auth.go
12
auth.go
@ -17,8 +17,8 @@ const AuthUserKey = "user"
|
||||
type Accounts map[string]string
|
||||
|
||||
type authPair struct {
|
||||
Value string
|
||||
User string
|
||||
value string
|
||||
user string
|
||||
}
|
||||
|
||||
type authPairs []authPair
|
||||
@ -28,8 +28,8 @@ func (a authPairs) searchCredential(authValue string) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
for _, pair := range a {
|
||||
if pair.Value == authValue {
|
||||
return pair.User, true
|
||||
if pair.value == authValue {
|
||||
return pair.user, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
@ -74,8 +74,8 @@ func processAccounts(accounts Accounts) authPairs {
|
||||
assert1(user != "", "User can not be empty")
|
||||
value := authorizationHeader(user, password)
|
||||
pairs = append(pairs, authPair{
|
||||
Value: value,
|
||||
User: user,
|
||||
value: value,
|
||||
user: user,
|
||||
})
|
||||
}
|
||||
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.Contains(t, pairs, authPair{
|
||||
User: "bar",
|
||||
Value: "Basic YmFyOmZvbw==",
|
||||
user: "bar",
|
||||
value: "Basic YmFyOmZvbw==",
|
||||
})
|
||||
assert.Contains(t, pairs, authPair{
|
||||
User: "foo",
|
||||
Value: "Basic Zm9vOmJhcg==",
|
||||
user: "foo",
|
||||
value: "Basic Zm9vOmJhcg==",
|
||||
})
|
||||
assert.Contains(t, pairs, authPair{
|
||||
User: "admin",
|
||||
Value: "Basic YWRtaW46cGFzc3dvcmQ=",
|
||||
user: "admin",
|
||||
value: "Basic YWRtaW46cGFzc3dvcmQ=",
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -449,10 +449,10 @@ func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error
|
||||
// Depending the "Content-Type" header different bindings are used:
|
||||
// "application/json" --> JSON 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 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 {
|
||||
b := binding.Default(c.Request.Method, c.ContentType())
|
||||
return c.MustBindWith(obj, b)
|
||||
|
@ -676,6 +676,7 @@ func TestContextRenderNoContentSecureJSON(t *testing.T) {
|
||||
func TestContextRenderHTML(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, router := CreateTestContext(w)
|
||||
|
||||
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
||||
router.SetHTMLTemplate(templ)
|
||||
|
||||
@ -686,6 +687,30 @@ func TestContextRenderHTML(t *testing.T) {
|
||||
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
|
||||
func TestContextRenderNoContentHTML(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
|
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())
|
||||
}
|
7
gin.go
7
gin.go
@ -160,11 +160,14 @@ func (engine *Engine) Delims(left, right string) *Engine {
|
||||
return engine
|
||||
}
|
||||
|
||||
// SecureJsonPrefix sets the secureJsonPrefix used in Context.SecureJSON.
|
||||
func (engine *Engine) SecureJsonPrefix(prefix string) *Engine {
|
||||
engine.secureJsonPrefix = prefix
|
||||
return engine
|
||||
}
|
||||
|
||||
// LoadHTMLGlob loads HTML files identified by glob pattern
|
||||
// and associates the result with HTML renderer.
|
||||
func (engine *Engine) LoadHTMLGlob(pattern string) {
|
||||
left := engine.delims.Left
|
||||
right := engine.delims.Right
|
||||
@ -179,6 +182,8 @@ func (engine *Engine) LoadHTMLGlob(pattern string) {
|
||||
engine.SetHTMLTemplate(templ)
|
||||
}
|
||||
|
||||
// LoadHTMLFiles loads a slice of HTML files
|
||||
// and associates the result with HTML renderer.
|
||||
func (engine *Engine) LoadHTMLFiles(files ...string) {
|
||||
if IsDebugging() {
|
||||
engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims}
|
||||
@ -189,6 +194,7 @@ func (engine *Engine) LoadHTMLFiles(files ...string) {
|
||||
engine.SetHTMLTemplate(templ)
|
||||
}
|
||||
|
||||
// SetHTMLTemplate associate a template with HTML renderer.
|
||||
func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
|
||||
if len(engine.trees) > 0 {
|
||||
debugPrintWARNINGSetHTMLTemplate()
|
||||
@ -197,6 +203,7 @@ func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
|
||||
engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)}
|
||||
}
|
||||
|
||||
// SetFuncMap sets the FuncMap used for template.FuncMap.
|
||||
func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
|
||||
engine.FuncMap = funcMap
|
||||
}
|
||||
|
@ -148,10 +148,8 @@ func (h xmlmap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := e.EncodeToken(xml.EndElement{Name: start.Name}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
return e.EncodeToken(xml.EndElement{Name: start.Name})
|
||||
}
|
||||
|
||||
func TestRenderYAML(t *testing.T) {
|
||||
|
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 {
|
||||
return func(c *Context) {
|
||||
f(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// WrapH is a helper function for wrapping http.Handler
|
||||
// Returns a Gin middleware
|
||||
func WrapH(h http.Handler) HandlerFunc {
|
||||
return func(c *Context) {
|
||||
h.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// H is a shortcup for map[string]interface{}
|
||||
type H map[string]interface{}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
if err := e.EncodeToken(xml.EndElement{Name: start.Name}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
return e.EncodeToken(xml.EndElement{Name: start.Name})
|
||||
}
|
||||
|
||||
func assert1(guard bool, text string) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user