diff --git a/net/ghttp/ghttp_middleware_handler_response.go b/net/ghttp/ghttp_middleware_handler_response.go index d78b4c194..574db5081 100644 --- a/net/ghttp/ghttp_middleware_handler_response.go +++ b/net/ghttp/ghttp_middleware_handler_response.go @@ -7,6 +7,7 @@ package ghttp import ( + "mime" "net/http" "github.com/gogf/gf/v2/errors/gcode" @@ -20,6 +21,17 @@ type DefaultHandlerResponse struct { Data interface{} `json:"data" dc:"Result data for certain request according API definition"` } +const ( + contentTypeEventStream = "text/event-stream" + contentTypeOctetStream = "application/octet-stream" + contentTypeMixedReplace = "multipart/x-mixed-replace" +) + +var ( + // streamContentType is the content types for stream response. + streamContentType = []string{contentTypeEventStream, contentTypeOctetStream, contentTypeMixedReplace} +) + // MiddlewareHandlerResponse is the default middleware handling handler response object and its error. func MiddlewareHandlerResponse(r *Request) { r.Middleware.Next() @@ -29,6 +41,14 @@ func MiddlewareHandlerResponse(r *Request) { return } + // It does not output common response content if it is stream response. + mediaType, _, _ := mime.ParseMediaType(r.Response.Header().Get("Content-Type")) + for _, ct := range streamContentType { + if mediaType == ct { + return + } + } + var ( msg string err = r.GetError() 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 4e58eab3d..691b426ab 100644 --- a/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go +++ b/net/ghttp/ghttp_z_unit_feature_middleware_basic_test.go @@ -772,6 +772,49 @@ func Test_MiddlewareHandlerGzipResponse(t *testing.T) { }) } +func Test_MiddlewareHandlerStreamResponse(t *testing.T) { + s := g.Server(guid.S()) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Middleware(ghttp.MiddlewareHandlerResponse) + + group.GET("/stream/event", func(r *ghttp.Request) { + r.Response.Header().Set("Content-Type", "text/event-stream") + }) + + group.GET("/stream/octet", func(r *ghttp.Request) { + r.Response.Header().Set("Content-Type", "application/octet-stream") + }) + + group.GET("/stream/mixed", func(r *ghttp.Request) { + r.Response.Header().Set("Content-Type", "multipart/x-mixed-replace") + }) + }) + 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())) + + rsp, err := client.Get(ctx, "/stream/event") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "") + + rsp, err = client.Get(ctx, "/stream/octet") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "") + + rsp, err = client.Get(ctx, "/stream/mixed") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "") + }) +} + type testTracerProvider struct{} var _ trace.TracerProvider = &testTracerProvider{}