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 =
>
CodePudding user response:
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. E.g. 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:])