为什么我无法在从转储构建HTTP请求时读取请求体?

huangapple go评论74阅读模式
英文:

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

问题

我正在尝试使用以下代码在Lambda中将SQS事件构建为HTTP请求。我能够获取到头部信息,但请求体为空。如果传入的请求有一个Content-Length头部,那么请求体中会有一些内容,但该请求是由外部系统生成的,不带有该头部。我做错了什么?

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))
}

输出:

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

请注意,我只会返回翻译好的部分,不会回答关于翻译的问题。

英文:

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 =
>

答案1

得分: 1

在这里你没有太多可以做的。带有非空主体的HTTP POST请求需要设置Content-Length(或分块传输编码)。如果源系统没有提供有效的HTTP请求,你需要在尝试读取请求之前确定内容长度并设置它。例如,可以像这样进行操作:

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:])
英文:

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:])

huangapple
  • 本文由 发表于 2022年8月19日 19:38:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/73416199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定