Description

context.JSON() adds a new line character \n to end of JSON response

How to reproduce

Clone this repo and run

$ GIN_MODE=release go run gin-newline.go

Expectations

Newline character ("\n") must not get added to the end of {"message":"hello world"}

Actual result

new line character gets added

Environment

  • go version: 1.13.5
  • gin version (or commit ref): v1.5.0
  • operating system: mac os

Comment From: jpninanjohn

Before 1.5, context.JSON was using json.Marshal Refer Here. In 1.5 this was changed to use encoder.Encode(). Refer Change

Encoder adds a line at the end. Refer to this code

An issue about this is raised in the golang repository also.

Comment From: KaushikNeelichetty

Linking the PR which caused this issue in the name of performance improvement trading correctness and that too without performance numbers.

Comment From: sayeedhussain

I am also facing an issue because of this redundant newline character addition.

I have a java service that sits in front a go service that is using gin framework.

  • The java service directly forwards the response headers from go service
  • The java service deserializes and then serializes the response json from go service using jackson which trims off the newline character.

Hence, the consumers of my java service are getting a content length mismatch issue between content-length header and actual content body.

gin-issue

Comment From: igorfraa

for those who do not appreciate this change and expect JSONs ending with newline, a straightforward middleware that appends a newline after every response:

// MiddlewareNewlineAppender returns a Gin middleware that should be executed just after the handler.
// It appends a newline character to the response for 'curl/*' useragent.
func MiddlewareNewlineAppender() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        ctx.Next() // First call the next handler in the chain.
        useragent := ctx.Request.UserAgent() // Then perform the actual job of appending a newline character.
        if strings.HasPrefix(useragent, "curl") {
                    _, _ = ctx.Writer.WriteString("\n")
        }
    }
}