简体   繁体   中英

Why am I not able to read the request body when I construct a HTTP request from a dump?

I am trying to construct a HTTP request out of a SQS event within a Lambda using the code below. I am able to get the headers but the request body is empty. If the incoming request has a Content-Length header, then there is some content in the body but the request is generated from an external system and it doesn't come with the header. What am I doing wrong?

package main

import (
    "bufio"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    sqsEvent := `{
    "Type" : "Notification",
    "MessageId" : "d66493a6-7e62-5104-9e8f-c8de60b5fb85",
    "TopicArn" : "arn:aws:sns:us-east-1:1234567890:msgbridge-my-sns-topic",
    "Message" : "POST /endpoint HTTP/1.1\r\nAccept: */*\r\nAccept-Encoding: deflate, gzip\r\nContent-Type: application/json\r\nX-Amzn-Trace-Id: Root=1-62fe1c96-098f3f26680ffa54742d9aa2\r\nX-Forwarded-For: 173.252.127.12\r\nX-Forwarded-Port: 443\r\nX-Forwarded-Proto: https\r\n\r\n{\"status\":\"ok\"}",
    "Timestamp" : "2022-08-18T11:03:51.069Z",
    "SignatureVersion" : "1",
    "Signature" : "s+M8QtMEYC5XfBIFIokrI8+ChHSTAzp7i+/1+hSkVQx/0vzQA7g6GQle5jrYPclrob2oIWy7FeEs+EGoKPZQ8YuxdZf6xrGIpV7qyVUcrLWpxm0HyYViJ3q/qbcjZPWmVxaYrOV30m1CBkpDcwYvFGHl0neFefkOpybZAdRgEXkbChAlanAiIgh91Sm1IWD4J1Doth1UF84afMov9TfSZMSgGQ+e7LCnNMtcSpUT34aDQDUxOB51NsLd9+tmYSzdqIanUQItcaB2zGJFp/yk2u6pJUjLJ1oybh3olgjhrmVQrO8mBTOVbMH3i/TyZUl1aogikhe+3hKQoDoCuMc/KQ=="
    }`
    var req struct {
        Message string `json:"Message"`
    }
    if err := json.Unmarshal([]byte(sqsEvent), &req); err != nil {
        fmt.Printf("error unmarshalling; error=%s\n", err)
        return
    }

    hreq, err := http.ReadRequest(bufio.NewReader(strings.NewReader(req.Message)))
    if err != nil {
        fmt.Printf("failed to convert message body to http request, error=%s\n", err)
        return
    }

    fmt.Printf("X-Amzn-Trace-Id=%s\n", hreq.Header.Get("X-Amzn-Trace-Id"))

    body, err := ioutil.ReadAll(hreq.Body)
    if err != nil {
        fmt.Printf("failed to read body, error=%s\n", err)
        return
    }
    fmt.Printf("Body = %s\n", string(body))
}

Output:

> go run .
X-Amzn-Trace-Id=Root=1-62fe1c96-098f3f26680ffa54742d9aa2
Body =
>

There is not much you can do here. HTTP POST requests with a non-empty body require a set Content-Length (or a chunked Transfer-Encoding). If the source system doesn't provide you a valid HTTP request you will have to determine the content length and set it before trying to read the request. Eg like

i := strings.Index(req.Message, "\r\n\r\n")
cl := len(req.Message) - i - 4
req.Message = fmt.Sprintf("%s\r\nContent-Length: %d%s",
        req.Message[:i], cl, req.Message[i:])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM