1
0
mirror of https://github.com/labstack/echo.git synced 2024-12-22 20:06:21 +02:00

Remove maxparam dependence from Context (#2611)

This commit is contained in:
Martti T 2024-03-21 23:42:16 +02:00 committed by GitHub
parent 011acb4732
commit d549290448
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 35 deletions

View File

@ -202,15 +202,29 @@ type Context interface {
type context struct { type context struct {
request *http.Request request *http.Request
response *Response response *Response
path string
pnames []string
pvalues []string
query url.Values query url.Values
handler HandlerFunc
store Map
echo *Echo echo *Echo
logger Logger logger Logger
lock sync.RWMutex
store Map
lock sync.RWMutex
// following fields are set by Router
// path is route path that Router matched. It is empty string where there is no route match.
// Route registered with RouteNotFound is considered as a match and path therefore is not empty.
path string
// pnames length is tied to param count for the matched route
pnames []string
// Usually echo.Echo is sizing pvalues but there could be user created middlewares that decide to
// overwrite parameter by calling SetParamNames + SetParamValues.
// When echo.Echo allocated that slice it length/capacity is tied to echo.Echo.maxParam value.
//
// It is important that pvalues size is always equal or bigger to pnames length.
pvalues []string
handler HandlerFunc
} }
const ( const (
@ -330,10 +344,6 @@ func (c *context) SetParamNames(names ...string) {
c.pnames = names c.pnames = names
l := len(names) l := len(names)
if *c.echo.maxParam < l {
*c.echo.maxParam = l
}
if len(c.pvalues) < l { if len(c.pvalues) < l {
// Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them, // Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them,
// probably those values will be overridden in a Context#SetParamValues // probably those values will be overridden in a Context#SetParamValues
@ -348,11 +358,11 @@ func (c *context) ParamValues() []string {
} }
func (c *context) SetParamValues(values ...string) { func (c *context) SetParamValues(values ...string) {
// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam at all times // NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam (or bigger) at all times
// It will brake the Router#Find code // It will brake the Router#Find code
limit := len(values) limit := len(values)
if limit > *c.echo.maxParam { if limit > len(c.pvalues) {
limit = *c.echo.maxParam c.pvalues = make([]string, limit)
} }
for i := 0; i < limit; i++ { for i := 0; i < limit; i++ {
c.pvalues[i] = values[i] c.pvalues[i] = values[i]
@ -643,8 +653,8 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
c.path = "" c.path = ""
c.pnames = nil c.pnames = nil
c.logger = nil c.logger = nil
// NOTE: Don't reset because it has to have length c.echo.maxParam at all times // NOTE: Don't reset because it has to have length c.echo.maxParam (or bigger) at all times
for i := 0; i < *c.echo.maxParam; i++ { for i := 0; i < len(c.pvalues); i++ {
c.pvalues[i] = "" c.pvalues[i] = ""
} }
} }

View File

@ -653,36 +653,50 @@ func TestContextGetAndSetParam(t *testing.T) {
}) })
} }
// Issue #1655 func TestContextSetParamNamesEchoMaxParam(t *testing.T) {
func TestContextSetParamNamesShouldUpdateEchoMaxParam(t *testing.T) {
e := New() e := New()
assert.Equal(t, 0, *e.maxParam) assert.Equal(t, 0, *e.maxParam)
expectedOneParam := []string{"one"} expectedOneParam := []string{"one"}
expectedTwoParams := []string{"one", "two"} expectedTwoParams := []string{"one", "two"}
expectedThreeParams := []string{"one", "two", ""} expectedThreeParams := []string{"one", "two", ""}
expectedABCParams := []string{"A", "B", "C"}
c := e.NewContext(nil, nil) {
c.SetParamNames("1", "2") c := e.AcquireContext()
c.SetParamValues(expectedTwoParams...) c.SetParamNames("1", "2")
assert.Equal(t, 2, *e.maxParam) c.SetParamValues(expectedTwoParams...)
assert.EqualValues(t, expectedTwoParams, c.ParamValues()) assert.Equal(t, 0, *e.maxParam) // has not been changed
assert.EqualValues(t, expectedTwoParams, c.ParamValues())
e.ReleaseContext(c)
}
c.SetParamNames("1") {
assert.Equal(t, 2, *e.maxParam) c := e.AcquireContext()
// Here for backward compatibility the ParamValues remains as they are c.SetParamNames("1", "2", "3")
assert.EqualValues(t, expectedOneParam, c.ParamValues()) c.SetParamValues(expectedThreeParams...)
assert.Equal(t, 0, *e.maxParam) // has not been changed
assert.EqualValues(t, expectedThreeParams, c.ParamValues())
e.ReleaseContext(c)
}
c.SetParamNames("1", "2", "3") { // values is always same size as names length
assert.Equal(t, 3, *e.maxParam) c := e.NewContext(nil, nil)
// Here for backward compatibility the ParamValues remains as they are, but the len is extended to e.maxParam c.SetParamValues([]string{"one", "two"}...) // more values than names should be ok
assert.EqualValues(t, expectedThreeParams, c.ParamValues()) c.SetParamNames("1")
assert.Equal(t, 0, *e.maxParam) // has not been changed
assert.EqualValues(t, expectedOneParam, c.ParamValues())
}
c.SetParamValues("A", "B", "C", "D") e.GET("/:id", handlerFunc)
assert.Equal(t, 3, *e.maxParam) assert.Equal(t, 1, *e.maxParam) // has not been changed
// Here D shouldn't be returned
assert.EqualValues(t, expectedABCParams, c.ParamValues()) {
c := e.NewContext(nil, nil)
c.SetParamValues([]string{"one", "two"}...)
c.SetParamNames("1")
assert.Equal(t, 1, *e.maxParam) // has not been changed
assert.EqualValues(t, expectedOneParam, c.ParamValues())
}
} }
func TestContextFormValue(t *testing.T) { func TestContextFormValue(t *testing.T) {