diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bf94fd1..1a259efc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # developing +- Fix 4396: Add context.param module into adapter. [4398](https://github.com/beego/beego/pull/4398) - Remove `duration` from prometheus labels. [4391](https://github.com/beego/beego/pull/4391) - Fix `unknown escape sequence` in generated code. [4385](https://github.com/beego/beego/pull/4385) - Using fixed name `commentRouter.go` as generated file name. [4385](https://github.com/beego/beego/pull/4385) diff --git a/adapter/context/param/conv.go b/adapter/context/param/conv.go new file mode 100644 index 00000000..ec4c6b7e --- /dev/null +++ b/adapter/context/param/conv.go @@ -0,0 +1,18 @@ +package param + +import ( + "reflect" + + beecontext "github.com/beego/beego/v2/adapter/context" + "github.com/beego/beego/v2/server/web/context" + "github.com/beego/beego/v2/server/web/context/param" +) + +// ConvertParams converts http method params to values that will be passed to the method controller as arguments +func ConvertParams(methodParams []*MethodParam, methodType reflect.Type, ctx *beecontext.Context) (result []reflect.Value) { + nps := make([]*param.MethodParam, 0, len(methodParams)) + for _, mp := range methodParams { + nps = append(nps, (*param.MethodParam)(mp)) + } + return param.ConvertParams(nps, methodType, (*context.Context)(ctx)) +} diff --git a/adapter/context/param/conv_test.go b/adapter/context/param/conv_test.go new file mode 100644 index 00000000..c27d385a --- /dev/null +++ b/adapter/context/param/conv_test.go @@ -0,0 +1,40 @@ +// Copyright 2020 beego +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package param + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/beego/beego/v2/adapter/context" +) + +func Demo(i int) { + +} + +func TestConvertParams(t *testing.T) { + res := ConvertParams(nil, reflect.TypeOf(Demo), context.NewContext()) + assert.Equal(t, 0, len(res)) + ctx := context.NewContext() + ctx.Input.RequestBody = []byte("11") + res = ConvertParams([]*MethodParam{ + New("A", InBody), + }, reflect.TypeOf(Demo), ctx) + assert.Equal(t, int64(11), res[0].Int()) +} + diff --git a/adapter/context/param/methodparams.go b/adapter/context/param/methodparams.go new file mode 100644 index 00000000..000539db --- /dev/null +++ b/adapter/context/param/methodparams.go @@ -0,0 +1,29 @@ +package param + +import ( + "github.com/beego/beego/v2/server/web/context/param" +) + +// MethodParam keeps param information to be auto passed to controller methods +type MethodParam param.MethodParam + +// New creates a new MethodParam with name and specific options +func New(name string, opts ...MethodParamOption) *MethodParam { + newOps := make([]param.MethodParamOption, 0, len(opts)) + for _, o := range opts { + newOps = append(newOps, oldMpoToNew(o)) + } + return (*MethodParam)(param.New(name, newOps...)) +} + +// Make creates an array of MethodParmas or an empty array +func Make(list ...*MethodParam) []*MethodParam { + if len(list) > 0 { + return list + } + return nil +} + +func (mp *MethodParam) String() string { + return (*param.MethodParam)(mp).String() +} diff --git a/adapter/context/param/methodparams_test.go b/adapter/context/param/methodparams_test.go new file mode 100644 index 00000000..b240d087 --- /dev/null +++ b/adapter/context/param/methodparams_test.go @@ -0,0 +1,34 @@ +// Copyright 2020 beego +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package param + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMethodParam_String(t *testing.T) { + method := New("myName", IsRequired, InHeader, Default("abc")) + s := method.String() + assert.Equal(t, `param.New("myName", param.IsRequired, param.InHeader, param.Default("abc"))`, s) +} + +func TestMake(t *testing.T) { + res := Make() + assert.Equal(t, 0, len(res)) + res = Make(New("myName", InBody)) + assert.Equal(t, 1, len(res)) +} diff --git a/adapter/context/param/options.go b/adapter/context/param/options.go new file mode 100644 index 00000000..1d9364c2 --- /dev/null +++ b/adapter/context/param/options.go @@ -0,0 +1,45 @@ +package param + +import ( + "github.com/beego/beego/v2/server/web/context/param" +) + +// MethodParamOption defines a func which apply options on a MethodParam +type MethodParamOption func(*MethodParam) + +// IsRequired indicates that this param is required and can not be omitted from the http request +var IsRequired MethodParamOption = func(p *MethodParam) { + param.IsRequired((*param.MethodParam)(p)) +} + +// InHeader indicates that this param is passed via an http header +var InHeader MethodParamOption = func(p *MethodParam) { + param.InHeader((*param.MethodParam)(p)) +} + +// InPath indicates that this param is part of the URL path +var InPath MethodParamOption = func(p *MethodParam) { + param.InPath((*param.MethodParam)(p)) +} + +// InBody indicates that this param is passed as an http request body +var InBody MethodParamOption = func(p *MethodParam) { + param.InBody((*param.MethodParam)(p)) +} + +// Default provides a default value for the http param +func Default(defaultValue interface{}) MethodParamOption { + return newMpoToOld(param.Default(defaultValue)) +} + +func newMpoToOld(n param.MethodParamOption) MethodParamOption { + return func(methodParam *MethodParam) { + n((*param.MethodParam)(methodParam)) + } +} + +func oldMpoToNew(old MethodParamOption) param.MethodParamOption { + return func(methodParam *param.MethodParam) { + old((*MethodParam)(methodParam)) + } +}