Search code examples
jsongogoroutineencoding-json-go

How to get json data from connection golang


I am sending curl request from the console using tcp connection written in golang. So it is basically a stream of data. I can successfully receive the data and store in the buffer using the following code

func PushDataToBuffer(bufferedChannel chan []byte, conn net.Conn) {
    defer conn.Close()
    fmt.Println("pushing messages into buffer...")

    buffer := make([]byte, 2048) // 2048 = assumption for reasonable event byte size

    for {
        n, err := conn.Read(buffer)
        if err != nil {
            fmt.Println("read error: ", err)
            continue // to continue listening for connections
        }
        bufferedChannel <- buffer[:n]
    }
}

However, when I try to read this data using this code:

for data := range bufferedChannel {
    fmt.Println("The len of buffer is: ", len(bufferedChannel))
    dataObject := models.Event{}
    err := json.Unmarshal(data, &dataObject)
}

I get the following error

Invalid character 'P' looking for beginning of value
2024/01/29 09:40:31 syntax error at byte offset 1

When I print out the data itself, I see this

POST / HTTP/1.1
Host: localhost:8952
User-Agent: curl/7.77.0
Accept: */*
Content-Type: application/json
Content-Length: 232

{\"customer\":\"Ada\",\"eventtype\":\"BuyingApples\",\"time\":\"0001-01-01T00:00:00Z\",\"specifics\":[{\"Key\":\"Shop\",\"Value\":\"Bakery\"},{\"Key\":\"Location\",\"Value\":\"Downtown\"},{\"Key\":\"recommends\",\"Value\":\"yes\"}]}

From the above, you can clearly see where the issue is. It is adding the header to the data so the P in POST is what golang is complaining of. That is why I cannot unmarshal it. So my question is this: How can I send the data to the server, or trim it when it arrives, that what I will be working with is just the json part:

{\"customer\":\"Ada\",\"eventtype\":\"BuyingApples\",\"time\":\"0001-01-01T00:00:00Z\",\"specifics\":[{\"Key\":\"Shop\",\"Value\":\"Bakery\"},{\"Key\":\"Location\",\"Value\":\"Downtown\"},{\"Key\":\"recommends\",\"Value\":\"yes\"}]}

P.S - I am using tcp connection to get the data not http

I have looked up various solutions online but I have not found any that suites my use case


Solution

  • cURL is not a TCP client. It's a HTTP client, and naturally generates some headers native to the protocol (such as the request method and path). And that is what ends up getting sent over the TCP connection. So there is a mismatch in what the server expects (plain TCP) and what the client sends (HTTP).

    You should update your server code to parse the raw data as a HTTP request with something like http.ReadRequest, OR simply use a client that sends the expected payload over the wire - i.e. plain TCP. Netcat will make this easy. Without knowing much about the problem you're solving I'd default to recommending the latter approach (because why send HTTP when TCP is expected in the first place?).