mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-21 08:42:16 +08:00
Resolve Conflict
This commit is contained in:
commit
f9c172abb3
@ -3,8 +3,6 @@ language: go
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- go: 1.6.x
|
||||
- go: 1.7.x
|
||||
- go: 1.8.x
|
||||
- go: 1.9.x
|
||||
- go: 1.10.x
|
||||
|
@ -69,7 +69,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi
|
||||
|
||||
To install Gin package, you need to install Go and set your Go workspace first.
|
||||
|
||||
1. Download and install it:
|
||||
1. The first need [Go](https://golang.org/) installed (**version 1.8+ is required**), then you can use the below Go command to install Gin.
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/gin-gonic/gin
|
||||
|
19
context.go
19
context.go
@ -439,11 +439,6 @@ func (c *Context) GetPostFormArray(key string) ([]string, bool) {
|
||||
if values := req.PostForm[key]; len(values) > 0 {
|
||||
return values, true
|
||||
}
|
||||
if req.MultipartForm != nil && req.MultipartForm.File != nil {
|
||||
if values := req.MultipartForm.Value[key]; len(values) > 0 {
|
||||
return values, true
|
||||
}
|
||||
}
|
||||
return []string{}, false
|
||||
}
|
||||
|
||||
@ -462,13 +457,7 @@ func (c *Context) GetPostFormMap(key string) (map[string]string, bool) {
|
||||
debugPrint("error on parse multipart form map: %v", err)
|
||||
}
|
||||
}
|
||||
dicts, exist := c.get(req.PostForm, key)
|
||||
|
||||
if !exist && req.MultipartForm != nil && req.MultipartForm.File != nil {
|
||||
dicts, exist = c.get(req.MultipartForm.Value, key)
|
||||
}
|
||||
|
||||
return dicts, exist
|
||||
return c.get(req.PostForm, key)
|
||||
}
|
||||
|
||||
// get is an internal method and returns a map which satisfy conditions.
|
||||
@ -828,6 +817,12 @@ func (c *Context) AsciiJSON(code int, obj interface{}) {
|
||||
c.Render(code, render.AsciiJSON{Data: obj})
|
||||
}
|
||||
|
||||
// PureJSON serializes the given struct as JSON into the response body.
|
||||
// PureJSON, unlike JSON, does not replace special html characters with their unicode entities.
|
||||
func (c *Context) PureJSON(code int, obj interface{}) {
|
||||
c.Render(code, render.PureJSON{Data: obj})
|
||||
}
|
||||
|
||||
// XML serializes the given struct as XML into the response body.
|
||||
// It also sets the Content-Type as "application/xml".
|
||||
func (c *Context) XML(code int, obj interface{}) {
|
||||
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package gin
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin/render"
|
||||
)
|
||||
|
||||
// PureJSON serializes the given struct as JSON into the response body.
|
||||
// PureJSON, unlike JSON, does not replace special html characters with their unicode entities.
|
||||
func (c *Context) PureJSON(code int, obj interface{}) {
|
||||
c.Render(code, render.PureJSON{Data: obj})
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package gin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Tests that the response is serialized as JSON
|
||||
// and Content-Type is set to application/json
|
||||
// and special HTML characters are preserved
|
||||
func TestContextRenderPureJSON(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := CreateTestContext(w)
|
||||
c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
|
||||
assert.Equal(t, http.StatusCreated, w.Code)
|
||||
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
|
||||
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
}
|
@ -622,8 +622,7 @@ func TestContextGetCookie(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestContextBodyAllowedForStatus(t *testing.T) {
|
||||
// todo(thinkerou): go1.6 not support StatusProcessing
|
||||
assert.False(t, false, bodyAllowedForStatus(102))
|
||||
assert.False(t, false, bodyAllowedForStatus(http.StatusProcessing))
|
||||
assert.False(t, false, bodyAllowedForStatus(http.StatusNoContent))
|
||||
assert.False(t, false, bodyAllowedForStatus(http.StatusNotModified))
|
||||
assert.True(t, true, bodyAllowedForStatus(http.StatusInternalServerError))
|
||||
@ -794,6 +793,18 @@ func TestContextRenderNoContentAsciiJSON(t *testing.T) {
|
||||
assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
// Tests that the response is serialized as JSON
|
||||
// and Content-Type is set to application/json
|
||||
// and special HTML characters are preserved
|
||||
func TestContextRenderPureJSON(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := CreateTestContext(w)
|
||||
c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
|
||||
assert.Equal(t, http.StatusCreated, w.Code)
|
||||
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
|
||||
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
// Tests that the response executes the templates
|
||||
// and responds with Content-Type set to text/html
|
||||
func TestContextRenderHTML(t *testing.T) {
|
||||
@ -1092,9 +1103,7 @@ func TestContextRenderRedirectAll(t *testing.T) {
|
||||
assert.Panics(t, func() { c.Redirect(299, "/resource") })
|
||||
assert.Panics(t, func() { c.Redirect(309, "/resource") })
|
||||
assert.NotPanics(t, func() { c.Redirect(http.StatusMultipleChoices, "/resource") })
|
||||
// todo(thinkerou): go1.6 not support StatusPermanentRedirect(308)
|
||||
// when we upgrade go version we can use http.StatusPermanentRedirect
|
||||
assert.NotPanics(t, func() { c.Redirect(308, "/resource") })
|
||||
assert.NotPanics(t, func() { c.Redirect(http.StatusPermanentRedirect, "/resource") })
|
||||
}
|
||||
|
||||
func TestContextNegotiationWithJSON(t *testing.T) {
|
||||
|
4
debug.go
4
debug.go
@ -14,7 +14,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const ginSupportMinGoVer = 6
|
||||
const ginSupportMinGoVer = 8
|
||||
|
||||
// IsDebugging returns true if the framework is running in debug mode.
|
||||
// Use SetMode(gin.ReleaseMode) to disable debug mode.
|
||||
@ -69,7 +69,7 @@ func getMinVer(v string) (uint64, error) {
|
||||
|
||||
func debugPrintWARNINGDefault() {
|
||||
if v, e := getMinVer(runtime.Version()); e == nil && v <= ginSupportMinGoVer {
|
||||
debugPrint(`[WARNING] Now Gin requires Go 1.6 or later and Go 1.7 will be required soon.
|
||||
debugPrint(`[WARNING] Now Gin requires Go 1.8 or later and Go 1.9 will be required soon.
|
||||
|
||||
`)
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ func TestDebugPrintWARNINGDefault(t *testing.T) {
|
||||
})
|
||||
m, e := getMinVer(runtime.Version())
|
||||
if e == nil && m <= ginSupportMinGoVer {
|
||||
assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.6 or later and Go 1.7 will be required soon.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
|
||||
assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.8 or later and Go 1.9 will be required soon.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
|
||||
} else {
|
||||
assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -69,6 +70,42 @@ func TestRunTLS(t *testing.T) {
|
||||
testRequest(t, "https://localhost:8443/example")
|
||||
}
|
||||
|
||||
func TestPusher(t *testing.T) {
|
||||
var html = template.Must(template.New("https").Parse(`
|
||||
<html>
|
||||
<head>
|
||||
<title>Https Test</title>
|
||||
<script src="/assets/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="color:red;">Welcome, Ginner!</h1>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
|
||||
router := New()
|
||||
router.Static("./assets", "./assets")
|
||||
router.SetHTMLTemplate(html)
|
||||
|
||||
go func() {
|
||||
router.GET("/pusher", func(c *Context) {
|
||||
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||
pusher.Push("/assets/app.js", nil)
|
||||
}
|
||||
c.String(http.StatusOK, "it worked")
|
||||
})
|
||||
|
||||
assert.NoError(t, router.RunTLS(":8449", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem"))
|
||||
}()
|
||||
|
||||
// have to wait for the goroutine to start and run the server
|
||||
// otherwise the main thread will complete
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
assert.Error(t, router.RunTLS(":8449", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem"))
|
||||
testRequest(t, "https://localhost:8449/pusher")
|
||||
}
|
||||
|
||||
func TestRunEmptyWithEnv(t *testing.T) {
|
||||
os.Setenv("PORT", "3123")
|
||||
router := New()
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package gin
|
||||
|
||||
import (
|
||||
|
@ -43,6 +43,11 @@ type AsciiJSON struct {
|
||||
// SecureJSONPrefix is a string which represents SecureJSON prefix.
|
||||
type SecureJSONPrefix string
|
||||
|
||||
// PureJSON contains the given interface object.
|
||||
type PureJSON struct {
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
var jsonContentType = []string{"application/json; charset=utf-8"}
|
||||
var jsonpContentType = []string{"application/javascript; charset=utf-8"}
|
||||
var jsonAsciiContentType = []string{"application/json"}
|
||||
@ -174,3 +179,16 @@ func (r AsciiJSON) Render(w http.ResponseWriter) (err error) {
|
||||
func (r AsciiJSON) WriteContentType(w http.ResponseWriter) {
|
||||
writeContentType(w, jsonAsciiContentType)
|
||||
}
|
||||
|
||||
// Render (PureJSON) writes custom ContentType and encodes the given interface object.
|
||||
func (r PureJSON) Render(w http.ResponseWriter) error {
|
||||
r.WriteContentType(w)
|
||||
encoder := json.NewEncoder(w)
|
||||
encoder.SetEscapeHTML(false)
|
||||
return encoder.Encode(r.Data)
|
||||
}
|
||||
|
||||
// WriteContentType (PureJSON) writes custom ContentType.
|
||||
func (r PureJSON) WriteContentType(w http.ResponseWriter) {
|
||||
writeContentType(w, jsonContentType)
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package render
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin/internal/json"
|
||||
)
|
||||
|
||||
// PureJSON contains the given interface object.
|
||||
type PureJSON struct {
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
// Render (PureJSON) writes custom ContentType and encodes the given interface object.
|
||||
func (r PureJSON) Render(w http.ResponseWriter) error {
|
||||
r.WriteContentType(w)
|
||||
encoder := json.NewEncoder(w)
|
||||
encoder.SetEscapeHTML(false)
|
||||
return encoder.Encode(r.Data)
|
||||
}
|
||||
|
||||
// WriteContentType (PureJSON) writes custom ContentType.
|
||||
func (r PureJSON) WriteContentType(w http.ResponseWriter) {
|
||||
writeContentType(w, jsonContentType)
|
||||
}
|
@ -18,9 +18,7 @@ type Redirect struct {
|
||||
|
||||
// Render (Redirect) redirects the http request to new location and writes redirect response.
|
||||
func (r Redirect) Render(w http.ResponseWriter) error {
|
||||
// todo(thinkerou): go1.6 not support StatusPermanentRedirect(308)
|
||||
// when we upgrade go version we can use http.StatusPermanentRedirect
|
||||
if (r.Code < 300 || r.Code > 308) && r.Code != 201 {
|
||||
if (r.Code < http.StatusMultipleChoices || r.Code > http.StatusPermanentRedirect) && r.Code != http.StatusCreated {
|
||||
panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code))
|
||||
}
|
||||
http.Redirect(w, r.Request, r.Location, r.Code)
|
||||
|
@ -1,26 +0,0 @@
|
||||
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package render
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRenderPureJSON(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
data := map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"html": "<b>",
|
||||
}
|
||||
err := (PureJSON{data}).Render(w)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
|
||||
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
}
|
@ -215,6 +215,18 @@ func TestRenderAsciiJSONFail(t *testing.T) {
|
||||
assert.Error(t, (AsciiJSON{data}).Render(w))
|
||||
}
|
||||
|
||||
func TestRenderPureJSON(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
data := map[string]interface{}{
|
||||
"foo": "bar",
|
||||
"html": "<b>",
|
||||
}
|
||||
err := (PureJSON{data}).Render(w)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
|
||||
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
type xmlmap map[string]interface{}
|
||||
|
||||
// Allows type H to be used with xml.Marshal
|
||||
|
@ -16,7 +16,8 @@ const (
|
||||
defaultStatus = http.StatusOK
|
||||
)
|
||||
|
||||
type responseWriterBase interface {
|
||||
// ResponseWriter ...
|
||||
type ResponseWriter interface {
|
||||
http.ResponseWriter
|
||||
http.Hijacker
|
||||
http.Flusher
|
||||
@ -37,6 +38,9 @@ type responseWriterBase interface {
|
||||
|
||||
// Forces to write the http header (status code + headers).
|
||||
WriteHeaderNow()
|
||||
|
||||
// get the http.Pusher for server push
|
||||
Pusher() http.Pusher
|
||||
}
|
||||
|
||||
type responseWriter struct {
|
||||
@ -113,3 +117,10 @@ func (w *responseWriter) Flush() {
|
||||
w.WriteHeaderNow()
|
||||
w.ResponseWriter.(http.Flusher).Flush()
|
||||
}
|
||||
|
||||
func (w *responseWriter) Pusher() (pusher http.Pusher) {
|
||||
if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
|
||||
return pusher
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
// +build !go1.8
|
||||
|
||||
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gin
|
||||
|
||||
// ResponseWriter ...
|
||||
type ResponseWriter interface {
|
||||
responseWriterBase
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// +build go1.8
|
||||
|
||||
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||
// Use of this source code is governed by a MIT style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ResponseWriter ...
|
||||
type ResponseWriter interface {
|
||||
responseWriterBase
|
||||
// get the http.Pusher for server push
|
||||
Pusher() http.Pusher
|
||||
}
|
||||
|
||||
func (w *responseWriter) Pusher() (pusher http.Pusher) {
|
||||
if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
|
||||
return pusher
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user