1

I wrote a web service (golang) using the gin framework to receive parameters in json body format. I make a request like this:

curl --location 'http://foo.bar/test' \
--header 'Content-Type: application/json' \
--data'{
     "a": "1",
     "b": "2"
}'

Now, I added a middleware that prints all request parameters to a log file, which runs one layer above the controller. Note that the specific type of the parameter is not known at the middleware layer. When I read the body and print the log, I get the following result:

[2023/06/20 11:44:38 CST] [INFO] (.../infra/log.Info:18) request_in||traceid=xx||spanid=xxx||path=/test||body= {
     "a": "1",
     "b": "2"
}

I expect something like this:

[2023/06/20 11:44:38 CST] [INFO] (/infra/log.Info:18) request_in||traceid=xx||spanid=xxx||path=/test||body={"a ":"1","b":"2"}

I would like to ask: How to remove the spaces and line breaks in the body? Note that the body parameter in this example is relatively simple, but the actual situation will be more complicated. Thanks.

andy ng
  • 23
  • 4
  • Please show us some [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – PRATHEESH PC Jun 20 '23 at 04:19
  • 2
    its you / curl sending the body like this. Nothing go can do about it and in case of json also nothing to worry about. It will unmarshal just fine. If you really want to you can hack something together like in below answers but I am not sure about that. Logging the body is probably not a good idea anyway. – The Fool Jun 20 '23 at 06:08

3 Answers3

1

You can Replace spaces and line breaks in the body by using the following approaches.

With strings.ReplaceAll()

requestBodyBytes, err := c.GetRawData()
if err != nil {
  // Handle this
}

body := string(requestBodyBytes)
body = strings.ReplaceAll(body, "\n", "")
body = strings.ReplaceAll(body, " ", "")

fmt.Printf("body=%v \n", body)

This method may be used when you need to change the request body by deleting spaces and lines before reaching it to the controller.

With Marshaling

requestBodyBytes, err := c.GetRawData()
if err != nil {
  // Handle this
}

var data interface{}
json.Unmarshal(requestBodyBytes, &data)

marshalledBytes, err := json.Marshal(data)
if err != nil {
  // Handle this
}
fmt.Printf("body=%v \n", string(marshalledBytes))

When you simply need to delete spaces and lines for logging, use this.

PRATHEESH PC
  • 1,461
  • 1
  • 3
  • 15
  • thanks. I think it is a good idea to use `Marshal` and `Unmarshal`, although there is a little performance loss. – andy ng Jun 20 '23 at 05:59
  • 2
    Use [json.Compact](https://pkg.go.dev/encoding/json#Compact) to remove insignificant whitespace from JSON documents. It's much more efficient because it doesn't have to build a bunch of useless maps and slices. – Peter Jun 20 '23 at 09:17
1

You can remove spaces and line breaks like this:

package main

import (
    "fmt"
)

func main() {
    data := []byte(`{
     "a": "1",
     "b": "2"
}`)

    i := 0
    for _, b := range data {
        switch b {
        case ' ', '\n', '\r':
        default:
            data[i] = b
            i++
        }
    }
    data = data[:i]

    fmt.Printf("%s\n", data)
}

Notes:

  1. It reuses the space of the current slice.

  2. Don't log request body like this. Reasons:

    1. The point of logging is to see what exactly is sent from the client. If the content is modified, it's not trust-able any more.
    2. Reading the request body in a middleware will affect the handlers executed afterward. Because the body has already been read, subsequent reads will get EOF most of the time. Of course you can store the body somewhere else and pass it to other handlers, but it's a waste of memory.
Zeke Lu
  • 6,349
  • 1
  • 17
  • 23
0
// Remove new line, tab, and space characters from a string
body = strings.ReplaceAll(body, "\n", "")
body = strings.ReplaceAll(body, " ", "")
body = strings.ReplaceAll(body, "\t", "")
sglmr
  • 21
  • 1
  • 5