diff --git a/net/ghttp/ghttp.go b/net/ghttp/ghttp.go index 0de8a833c..a8667391d 100644 --- a/net/ghttp/ghttp.go +++ b/net/ghttp/ghttp.go @@ -12,6 +12,8 @@ import ( "reflect" "time" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gorilla/websocket" "github.com/gogf/gf/v2/container/gmap" @@ -175,3 +177,10 @@ var ( // defaultValueTags are the struct tag names for default value storing. defaultValueTags = []string{"d", "default"} ) + +var ( + ErrNeedJsonBody = gerror.NewOption(gerror.Option{ + Text: "the request body content should be JSON format", + Code: gcode.CodeInvalidRequest, + }) +) diff --git a/net/ghttp/ghttp_middleware_json_body.go b/net/ghttp/ghttp_middleware_json_body.go new file mode 100644 index 000000000..eb3263ec9 --- /dev/null +++ b/net/ghttp/ghttp_middleware_json_body.go @@ -0,0 +1,23 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package ghttp + +import ( + "github.com/gogf/gf/v2/internal/json" +) + +// MiddlewareJsonBody validates and returns request body whether JSON format. +func MiddlewareJsonBody(r *Request) { + requestBody := r.GetBody() + if len(requestBody) > 0 { + if !json.Valid(requestBody) { + r.SetError(ErrNeedJsonBody) + return + } + } + r.Middleware.Next() +} diff --git a/net/ghttp/ghttp_server_handler.go b/net/ghttp/ghttp_server_handler.go index 184809496..4e8635198 100644 --- a/net/ghttp/ghttp_server_handler.go +++ b/net/ghttp/ghttp_server_handler.go @@ -148,6 +148,11 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { if request.Response.Status == 0 { if request.StaticFile != nil || request.Middleware.served || request.Response.buffer.Len() > 0 { request.Response.WriteHeader(http.StatusOK) + } else if err := request.GetError(); err != nil { + if request.Response.BufferLength() == 0 { + request.Response.Write(err.Error()) + } + request.Response.WriteHeader(http.StatusInternalServerError) } else { request.Response.WriteHeader(http.StatusNotFound) } diff --git a/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go b/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go index af81b245d..7622cf466 100644 --- a/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go +++ b/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go @@ -674,3 +674,26 @@ func Test_Middleware_Panic(t *testing.T) { t.Assert(client.GetContent(ctx, "/"), "exception recovered: error") }) } + +func Test_Middleware_JsonBody(t *testing.T) { + s := g.Server(guid.S()) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Middleware(ghttp.MiddlewareJsonBody) + group.ALL("/", func(r *ghttp.Request) { + r.Response.Write("hello") + }) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + t.Assert(client.GetContent(ctx, "/"), "hello") + t.Assert(client.PutContent(ctx, "/"), "hello") + t.Assert(client.PutContent(ctx, "/", `{"name":"john"}`), "hello") + t.Assert(client.PutContent(ctx, "/", `{"name":}`), "the request body content should be JSON format") + }) +}