Merge pull request #4579 from byene0923/develop

Proposal:Add Bind() method for web.Controller
This commit is contained in:
Ming Deng 2021-04-19 22:16:19 +08:00 committed by GitHub
commit 51cb4fec0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 2 deletions

View File

@ -33,8 +33,8 @@
- Improve: Avoid ignoring mistakes that need attention [4548](https://github.com/beego/beego/pull/4548) - Improve: Avoid ignoring mistakes that need attention [4548](https://github.com/beego/beego/pull/4548)
- Integration: DeepSource [4560](https://github.com/beego/beego/pull/4560) - Integration: DeepSource [4560](https://github.com/beego/beego/pull/4560)
- Integration: Remove unnecessary function call [4577](https://github.com/beego/beego/pull/4577) - Integration: Remove unnecessary function call [4577](https://github.com/beego/beego/pull/4577)
- Feature issue #4402 finish router get example. [4416](https://github.com/beego/beego/pull/4416)
- Proposal: Add Bind() method for web.Controller [4491](https://github.com/beego/beego/issues/4491)
## Fix Sonar ## Fix Sonar
- [4473](https://github.com/beego/beego/pull/4473) - [4473](https://github.com/beego/beego/pull/4473)

View File

@ -17,8 +17,12 @@ package web
import ( import (
"bytes" "bytes"
context2 "context" context2 "context"
"encoding/json"
"encoding/xml"
"errors" "errors"
"fmt" "fmt"
"github.com/gogo/protobuf/proto"
"gopkg.in/yaml.v2"
"html/template" "html/template"
"io" "io"
"mime/multipart" "mime/multipart"
@ -239,6 +243,50 @@ func (c *Controller) HandlerFunc(fnname string) bool {
// URLMapping register the internal Controller router. // URLMapping register the internal Controller router.
func (c *Controller) URLMapping() {} func (c *Controller) URLMapping() {}
func (c *Controller) Bind(obj interface{}) error {
ct, exist := c.Ctx.Request.Header["Content-Type"]
if !exist || len(ct) == 0 {
return c.BindJson(obj)
}
i, l := 0, len(ct[0])
for ; i < l && ct[0][i] != ';'; i++ {
}
switch ct[0][0:i] {
case "application/json":
return c.BindJson(obj)
case "application/xml", "text/xml":
return c.BindXML(obj)
case "application/x-www-form-urlencoded":
return c.BindForm(obj)
case "application/x-protobuf":
return c.BindProtobuf(obj)
case "application/x-yaml":
return c.BindYAML(obj)
default:
return errors.New("Unsupported Content-Type:" + ct[0])
}
}
func (c *Controller) BindYAML(obj interface{}) error {
return yaml.Unmarshal(c.Ctx.Input.RequestBody, obj)
}
func (c *Controller) BindForm(obj interface{}) error {
return c.ParseForm(obj)
}
func (c *Controller) BindJson(obj interface{}) error {
return json.Unmarshal(c.Ctx.Input.RequestBody, obj)
}
func (c *Controller) BindProtobuf(obj interface{}) error {
return proto.Unmarshal(c.Ctx.Input.RequestBody, obj.(proto.Message))
}
func (c *Controller) BindXML(obj interface{}) error {
return xml.Unmarshal(c.Ctx.Input.RequestBody, obj)
}
// Mapping the method to function // Mapping the method to function
func (c *Controller) Mapping(method string, fn func()) { func (c *Controller) Mapping(method string, fn func()) {
c.methodMapping[method] = fn c.methodMapping[method] = fn

View File

@ -15,7 +15,10 @@
package web package web
import ( import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"math" "math"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -180,3 +183,64 @@ func TestAdditionalViewPaths(t *testing.T) {
ctrl.ViewPath = dir2 ctrl.ViewPath = dir2
ctrl.RenderString() ctrl.RenderString()
} }
func TestBindJson(t *testing.T) {
var s struct {
Foo string `json:"foo"`
}
header := map[string][]string{"Content-Type": {"application/json"}}
request := &http.Request{Header: header}
input := &context.BeegoInput{RequestBody: []byte(`{"foo": "FOO"}`)}
ctx := &context.Context{Request: request, Input: input}
ctrlr := Controller{Ctx: ctx}
err := ctrlr.Bind(&s)
require.NoError(t, err)
assert.Equal(t, "FOO", s.Foo)
}
func TestBindNoContentType(t *testing.T) {
var s struct {
Foo string `json:"foo"`
}
header := map[string][]string{}
request := &http.Request{Header: header}
input := &context.BeegoInput{RequestBody: []byte(`{"foo": "FOO"}`)}
ctx := &context.Context{Request: request, Input: input}
ctrlr := Controller{Ctx: ctx}
err := ctrlr.Bind(&s)
require.NoError(t, err)
assert.Equal(t, "FOO", s.Foo)
}
func TestBindXML(t *testing.T) {
var s struct {
Foo string `xml:"foo"`
}
xmlBody := `<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
</root>`
header := map[string][]string{"Content-Type": {"text/xml"}}
request := &http.Request{Header: header}
input := &context.BeegoInput{RequestBody: []byte(xmlBody)}
ctx := &context.Context{Request: request, Input: input}
ctrlr := Controller{Ctx: ctx}
err := ctrlr.Bind(&s)
require.NoError(t, err)
assert.Equal(t, "FOO", s.Foo)
}
func TestBindYAML(t *testing.T) {
var s struct {
Foo string `yaml:"foo"`
}
header := map[string][]string{"Content-Type": {"application/x-yaml"}}
request := &http.Request{Header: header}
input := &context.BeegoInput{RequestBody: []byte("foo: FOO")}
ctx := &context.Context{Request: request, Input: input}
ctrlr := Controller{Ctx: ctx}
err := ctrlr.Bind(&s)
require.NoError(t, err)
assert.Equal(t, "FOO", s.Foo)
}