Merge branch 'develop' of https://github.com/beego/beego into develop

This commit is contained in:
holooooo 2021-05-16 14:20:31 +08:00
commit 9b418271cc
6 changed files with 109 additions and 25 deletions

View File

@ -1,5 +1,6 @@
# developing
- Add http client and option func. [4455](https://github.com/beego/beego/issues/4455)
- Add: Resp() method for web.Controller. [4588](https://github.com/beego/beego/pull/4588)
- Web mock and test support. [4565](https://github.com/beego/beego/pull/4565) [4574](https://github.com/beego/beego/pull/4574)
- Error codes definition of cache module. [4493](https://github.com/beego/beego/pull/4493)
- Remove generateCommentRoute http hook. Using `bee generate routers` commands instead.[4486](https://github.com/beego/beego/pull/4486) [bee PR 762](https://github.com/beego/bee/pull/762)
@ -37,6 +38,7 @@
- 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/4579)
- Optimize AddAutoPrefix: only register one router in case-insensitive mode. [4582](https://github.com/beego/beego/pull/4582)
- Init exceptMethod by using reflection. [4583](https://github.com/beego/beego/pull/4583)
## Fix Sonar
- [4473](https://github.com/beego/beego/pull/4473)

View File

@ -21,8 +21,6 @@ import (
"encoding/xml"
"errors"
"fmt"
"github.com/gogo/protobuf/proto"
"gopkg.in/yaml.v2"
"html/template"
"io"
"mime/multipart"
@ -37,6 +35,8 @@ import (
"github.com/beego/beego/v2/server/web/context"
"github.com/beego/beego/v2/server/web/context/param"
"github.com/beego/beego/v2/server/web/session"
"github.com/gogo/protobuf/proto"
"gopkg.in/yaml.v2"
)
var (
@ -436,6 +436,22 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
}
return URLFor(endpoint, values...)
}
// Resp sends response based on the Accept Header
// By default response will be in JSON
func (c *Controller) Resp(data interface{}) error {
accept := c.Ctx.Input.Header("Accept")
switch accept {
case context.ApplicationYAML:
c.Data["yaml"] = data
return c.ServeYAML()
case context.ApplicationXML, context.TextXML:
c.Data["xml"] = data
return c.ServeXML()
default:
c.Data["json"] = data
return c.ServeJSON()
}
}
// ServeJSON sends a json response with encoding charset.
func (c *Controller) ServeJSON(encoding ...bool) error {

View File

@ -15,16 +15,18 @@
package web
import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"io/ioutil"
"math"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strconv"
"testing"
"github.com/beego/beego/v2/server/web/context"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetInt(t *testing.T) {
@ -244,3 +246,67 @@ func TestBindYAML(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "FOO", s.Foo)
}
type TestRespController struct {
Controller
}
func (t *TestRespController) TestResponse() {
type S struct {
Foo string `json:"foo" xml:"foo" yaml:"foo"`
}
bar := S{Foo: "bar"}
_ = t.Resp(bar)
}
type respTestCase struct {
Accept string
ExpectedContentLength int64
ExpectedResponse string
}
func TestControllerResp(t *testing.T) {
// test cases
tcs := []respTestCase{
{Accept: context.ApplicationJSON, ExpectedContentLength: 18, ExpectedResponse: "{\n \"foo\": \"bar\"\n}"},
{Accept: context.ApplicationXML, ExpectedContentLength: 25, ExpectedResponse: "<S>\n <foo>bar</foo>\n</S>"},
{Accept: context.ApplicationYAML, ExpectedContentLength: 9, ExpectedResponse: "foo: bar\n"},
{Accept: "OTHER", ExpectedContentLength: 18, ExpectedResponse: "{\n \"foo\": \"bar\"\n}"},
}
for _, tc := range tcs {
testControllerRespTestCases(t, tc)
}
}
func testControllerRespTestCases(t *testing.T, tc respTestCase) {
// create fake GET request
r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Accept", tc.Accept)
w := httptest.NewRecorder()
// setup the handler
handler := NewControllerRegister()
handler.Add("/", &TestRespController{}, WithRouterMethods(&TestRespController{}, "get:TestResponse"))
handler.ServeHTTP(w, r)
response := w.Result()
if response.ContentLength != tc.ExpectedContentLength {
t.Errorf("TestResponse() unable to validate content length %d for %s", response.ContentLength, tc.Accept)
}
if response.StatusCode != http.StatusOK {
t.Errorf("TestResponse() failed to validate response code for %s", tc.Accept)
}
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
t.Errorf("TestResponse() failed to parse response body for %s", tc.Accept)
}
bodyString := string(bodyBytes)
if bodyString != tc.ExpectedResponse {
t.Errorf("TestResponse() failed to validate response body '%s' for %s", bodyString, tc.Accept)
}
}

View File

@ -2,13 +2,12 @@ package web
import (
"encoding/json"
"mime"
"net/http"
"path/filepath"
"github.com/beego/beego/v2/core/logs"
"github.com/beego/beego/v2/server/web/context"
"github.com/beego/beego/v2/server/web/session"
"mime"
"net/http"
"path/filepath"
)
// register MIME type with content type

View File

@ -69,20 +69,8 @@ var (
"UNLOCK": true,
}
// these web.Controller's methods shouldn't reflect to AutoRouter
exceptMethod = []string{"Abort", "CheckXSRFCookie", "CustomAbort", "DelSession",
"DestroySession", "Finish", "GetBool", "GetControllerAndAction",
"GetFile", "GetFiles", "GetFloat", "GetInt", "GetInt16",
"GetInt32", "GetInt64", "GetInt8", "GetSecureCookie", "GetSession",
"GetString", "GetStrings", "GetUint16", "GetUint32", "GetUint64",
"GetUint8", "HandlerFunc", "Init", "Input",
"IsAjax", "Mapping", "ParseForm",
"Prepare", "Redirect", "Render", "RenderBytes",
"RenderString", "SaveToFile", "SaveToFileWithBuffer", "SaveToFileWithBuffer",
"ServeFormatted", "ServeJSON", "ServeJSONP", "ServeXML", "ServeYAML",
"SessionRegenerateID", "SetData", "SetSecureCookie", "SetSession", "StartSession",
"StopRun", "URLFor", "URLMapping", "XSRFFormHTML",
"XSRFToken",
}
// see registerControllerExceptMethods
exceptMethod = initExceptMethod()
urlPlaceholder = "{{placeholder}}"
// DefaultAccessLogFilter will skip the accesslog if return true
@ -116,6 +104,17 @@ func ExceptMethodAppend(action string) {
exceptMethod = append(exceptMethod, action)
}
func initExceptMethod() []string {
res := make([]string, 0, 32)
c := &Controller{}
t := reflect.TypeOf(c)
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
res = append(res, m.Name)
}
return res
}
// ControllerInfo holds information about the controller.
type ControllerInfo struct {
pattern string

View File

@ -137,10 +137,12 @@ func TestUrlFor(t *testing.T) {
func TestUrlFor3(t *testing.T) {
handler := NewControllerRegister()
handler.AddAuto(&TestController{})
if a := handler.URLFor("TestController.Myext"); a != "/test/myext" && a != "/Test/Myext" {
a := handler.URLFor("TestController.Myext")
if a != "/test/myext" && a != "/Test/Myext" {
t.Errorf("TestController.Myext must equal to /test/myext, but get " + a)
}
if a := handler.URLFor("TestController.GetURL"); a != "/test/geturl" && a != "/Test/GetURL" {
a = handler.URLFor("TestController.GetURL")
if a != "/test/geturl" && a != "/Test/GetURL" {
t.Errorf("TestController.GetURL must equal to /test/geturl, but get " + a)
}
}