mirror of
https://github.com/gin-gonic/gin.git
synced 2026-07-24 22:55:45 +08:00
Compare commits
5 Commits
778833f365
...
6ea0e60a17
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ea0e60a17 | ||
|
|
19b877fa50 | ||
|
|
39122a594e | ||
|
|
d0c802af21 | ||
|
|
322da9ca24 |
26
context.go
26
context.go
@ -280,7 +280,7 @@ func (c *Context) Error(err error) *Error {
|
||||
|
||||
// Set is used to store a new key/value pair exclusively for this context.
|
||||
// It also lazy initializes c.Keys if it was not used previously.
|
||||
func (c *Context) Set(key any, value any) {
|
||||
func (c *Context) Set(key any, value any) *Context {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.Keys == nil {
|
||||
@ -288,6 +288,7 @@ func (c *Context) Set(key any, value any) {
|
||||
}
|
||||
|
||||
c.Keys[key] = value
|
||||
return c
|
||||
}
|
||||
|
||||
// Get returns the value for the given key, ie: (value, true).
|
||||
@ -506,8 +507,9 @@ func (c *Context) Param(key string) string {
|
||||
// Example Route: "/user/:id"
|
||||
// AddParam("id", 1)
|
||||
// Result: "/user/1"
|
||||
func (c *Context) AddParam(key, value string) {
|
||||
func (c *Context) AddParam(key, value string) *Context {
|
||||
c.Params = append(c.Params, Param{Key: key, Value: value})
|
||||
return c
|
||||
}
|
||||
|
||||
// Query returns the keyed url query value if it exists,
|
||||
@ -1052,19 +1054,21 @@ func bodyAllowedForStatus(status int) bool {
|
||||
}
|
||||
|
||||
// Status sets the HTTP response code.
|
||||
func (c *Context) Status(code int) {
|
||||
func (c *Context) Status(code int) *Context {
|
||||
c.Writer.WriteHeader(code)
|
||||
return c
|
||||
}
|
||||
|
||||
// Header is an intelligent shortcut for c.Writer.Header().Set(key, value).
|
||||
// It writes a header in the response.
|
||||
// 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) *Context {
|
||||
if value == "" {
|
||||
c.Writer.Header().Del(key)
|
||||
return
|
||||
return c
|
||||
}
|
||||
c.Writer.Header().Set(key, value)
|
||||
return c
|
||||
}
|
||||
|
||||
// GetHeader returns value from request headers.
|
||||
@ -1081,14 +1085,15 @@ func (c *Context) GetRawData() ([]byte, error) {
|
||||
}
|
||||
|
||||
// SetSameSite with cookie
|
||||
func (c *Context) SetSameSite(samesite http.SameSite) {
|
||||
func (c *Context) SetSameSite(samesite http.SameSite) *Context {
|
||||
c.sameSite = samesite
|
||||
return c
|
||||
}
|
||||
|
||||
// SetCookie adds a Set-Cookie header to the ResponseWriter's headers.
|
||||
// The provided cookie must have a valid Name. Invalid cookies may be
|
||||
// silently dropped.
|
||||
func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) {
|
||||
func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) *Context {
|
||||
if path == "" {
|
||||
path = "/"
|
||||
}
|
||||
@ -1102,12 +1107,13 @@ func (c *Context) SetCookie(name, value string, maxAge int, path, domain string,
|
||||
Secure: secure,
|
||||
HttpOnly: httpOnly,
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
// SetCookieData adds a Set-Cookie header to the ResponseWriter's headers.
|
||||
// It accepts a pointer to http.Cookie structure for more flexibility in setting cookie attributes.
|
||||
// The provided cookie must have a valid Name. Invalid cookies may be silently dropped.
|
||||
func (c *Context) SetCookieData(cookie *http.Cookie) {
|
||||
func (c *Context) SetCookieData(cookie *http.Cookie) *Context {
|
||||
if cookie.Path == "" {
|
||||
cookie.Path = "/"
|
||||
}
|
||||
@ -1115,6 +1121,7 @@ func (c *Context) SetCookieData(cookie *http.Cookie) {
|
||||
cookie.SameSite = c.sameSite
|
||||
}
|
||||
http.SetCookie(c.Writer, cookie)
|
||||
return c
|
||||
}
|
||||
|
||||
// Cookie returns the named cookie provided in the request or
|
||||
@ -1394,8 +1401,9 @@ func (c *Context) NegotiateFormat(offered ...string) string {
|
||||
}
|
||||
|
||||
// SetAccepted sets Accept header data.
|
||||
func (c *Context) SetAccepted(formats ...string) {
|
||||
func (c *Context) SetAccepted(formats ...string) *Context {
|
||||
c.Accepted = formats
|
||||
return c
|
||||
}
|
||||
|
||||
/************************************/
|
||||
|
||||
@ -3677,3 +3677,46 @@ func BenchmarkGetMapFromFormData(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContextChaining(t *testing.T) {
|
||||
c, _ := CreateTestContext(httptest.NewRecorder())
|
||||
// Basic cookie settings
|
||||
cookie := &http.Cookie{
|
||||
Name: "name",
|
||||
Value: "gin",
|
||||
MaxAge: 1,
|
||||
Path: "/",
|
||||
Domain: "localhost",
|
||||
Secure: true,
|
||||
HttpOnly: true,
|
||||
}
|
||||
|
||||
c.Set("foo", "bar").
|
||||
AddParam("id", "1").
|
||||
SetSameSite(http.SameSiteLaxMode).
|
||||
SetCookie("user", "gin", 1, "/", "localhost", true, true).
|
||||
SetCookieData(cookie).
|
||||
Header("Content-Type", "text/plain").
|
||||
Header("X-Custom", "value").
|
||||
SetAccepted(MIMEJSON, MIMEXML).
|
||||
Status(200)
|
||||
|
||||
value, err := c.Get("foo")
|
||||
assert.Equal(t, "bar", value)
|
||||
assert.True(t, err)
|
||||
|
||||
v, ok := c.Params.Get("id")
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "1", v)
|
||||
|
||||
assert.Equal(t, []string{"user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", "name=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure"}, c.Writer.Header().Values("Set-Cookie"))
|
||||
|
||||
assert.Equal(t, "text/plain", c.Writer.Header().Get("Content-Type"))
|
||||
assert.Equal(t, "value", c.Writer.Header().Get("X-Custom"))
|
||||
|
||||
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML)) //nolint:testifylint
|
||||
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
|
||||
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON)) //nolint:testifylint
|
||||
|
||||
assert.Equal(t, 200, c.Writer.Status())
|
||||
}
|
||||
|
||||
4
debug.go
4
debug.go
@ -15,6 +15,8 @@ import (
|
||||
|
||||
const ginSupportMinGoVer = 24
|
||||
|
||||
var runtimeVersion = runtime.Version()
|
||||
|
||||
// IsDebugging returns true if the framework is running in debug mode.
|
||||
// Use SetMode(gin.ReleaseMode) to disable debug mode.
|
||||
func IsDebugging() bool {
|
||||
@ -77,7 +79,7 @@ func getMinVer(v string) (uint64, error) {
|
||||
}
|
||||
|
||||
func debugPrintWARNINGDefault() {
|
||||
if v, e := getMinVer(runtime.Version()); e == nil && v < ginSupportMinGoVer {
|
||||
if v, e := getMinVer(runtimeVersion); e == nil && v < ginSupportMinGoVer {
|
||||
debugPrint(`[WARNING] Now Gin requires Go 1.24+.
|
||||
|
||||
`)
|
||||
|
||||
@ -12,7 +12,6 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@ -21,10 +20,6 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TODO
|
||||
// func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) {
|
||||
// func debugPrint(format string, values ...any) {
|
||||
|
||||
func TestIsDebugging(t *testing.T) {
|
||||
SetMode(DebugMode)
|
||||
assert.True(t, IsDebugging())
|
||||
@ -48,6 +43,18 @@ func TestDebugPrint(t *testing.T) {
|
||||
assert.Equal(t, "[GIN-debug] these are 2 error messages\n", re)
|
||||
}
|
||||
|
||||
func TestDebugPrintFunc(t *testing.T) {
|
||||
DebugPrintFunc = func(format string, values ...any) {
|
||||
fmt.Fprintf(DefaultWriter, "[GIN-debug] "+format, values...)
|
||||
}
|
||||
re := captureOutput(t, func() {
|
||||
SetMode(DebugMode)
|
||||
debugPrint("debug print func test: %d", 123)
|
||||
SetMode(TestMode)
|
||||
})
|
||||
assert.Regexp(t, `^\[GIN-debug\] debug print func test: 123`, re)
|
||||
}
|
||||
|
||||
func TestDebugPrintError(t *testing.T) {
|
||||
re := captureOutput(t, func() {
|
||||
SetMode(DebugMode)
|
||||
@ -104,12 +111,17 @@ func TestDebugPrintWARNINGDefault(t *testing.T) {
|
||||
debugPrintWARNINGDefault()
|
||||
SetMode(TestMode)
|
||||
})
|
||||
m, e := getMinVer(runtime.Version())
|
||||
if e == nil && m < ginSupportMinGoVer {
|
||||
assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.24+.\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)
|
||||
}
|
||||
assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
|
||||
}
|
||||
|
||||
func TestDebugPrintWARNINGDefaultWithUnsupportedVersion(t *testing.T) {
|
||||
runtimeVersion = "go1.23.12"
|
||||
re := captureOutput(t, func() {
|
||||
SetMode(DebugMode)
|
||||
debugPrintWARNINGDefault()
|
||||
SetMode(TestMode)
|
||||
})
|
||||
assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.24+.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
|
||||
}
|
||||
|
||||
func TestDebugPrintWARNINGNew(t *testing.T) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user