-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Description
- With issues:
- Use the search tool before opening a new issue.
- Please provide source code and commit sha if you found a bug.
- Review existing issues and provide feedback or react to them.
Description
#2755 only fixes the slice bounds out of range
panic. Route params are not be handled correctly in test context. I can explain what happened.
When call CreateTestContext
, it will call New
function to create a Engine
. The maxParams
will be the default value 0
.
Lines 9 to 16 in 9c27053
// CreateTestContext returns a fresh engine and context for testing purposes | |
func CreateTestContext(w http.ResponseWriter) (c *Context, r *Engine) { | |
r = New() | |
c = r.allocateContext() | |
c.reset() | |
c.writermem.reset(w) | |
return | |
} |
Then allocateContext
init the Params
. The cap
and len
are both 0. params
is the reference of Params
.
Lines 202 to 205 in 9c27053
func (engine *Engine) allocateContext() *Context { | |
v := make(Params, 0, engine.maxParams) | |
return &Context{engine: engine, params: &v} | |
} |
Even if we add a route, it only incrs the maxParams
value, it has not effect on the Context
we created by CreateTestContext
before. The condition will always be false
.
Lines 462 to 479 in 9c27053
if params != nil && cap(*params) > 0 { | |
if value.params == nil { | |
value.params = params | |
} | |
// Expand slice within preallocated capacity | |
i := len(*value.params) | |
*value.params = (*value.params)[:i+1] | |
val := path[:end] | |
if unescape { | |
if v, err := url.QueryUnescape(val); err == nil { | |
val = v | |
} | |
} | |
(*value.params)[i] = Param{ | |
Key: n.path[1:], | |
Value: val, | |
} | |
} |
How to reproduce
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/gin-gonic/gin"
)
func main() {
w := httptest.NewRecorder()
ctx, engine := gin.CreateTestContext(w)
engine.GET("/hello/:name", func(ctx *gin.Context) {
fmt.Printf("Param name is %s\n", ctx.Param("name"))
ctx.String(http.StatusOK, "Hello %s", ctx.Param("name"))
})
var err error
ctx.Request, err = http.NewRequest(http.MethodGet, "/hello/world", nil)
if err != nil {
panic(err)
}
engine.HandleContext(ctx)
}
Expectations
Get following output after running the code.
[GIN-debug] GET /hello/:name --> main.main.func1 (1 handlers)
Param name is world
Actual result
[GIN-debug] GET /hello/:name --> main.main.func1 (1 handlers)
Param name is
ctx.Param("name")
returns a empty string.
Environment
- go version: go version go1.16 darwin/amd64
- gin version (or commit ref): v1.7.2-0.20210704023713-9c27053243cb
- operating system: macOs Big Sur 11.4, Darwin Kernel Version 20.5.0