http.Request
의 Body
에 여러 번 액세스하고 싶습니다. 처음으로 내 인증 미들웨어에서 발생하고,이를 사용하여 sha256 서명을 다시 만듭니다. 두 번째 시간이 지나면 JSON으로 구문 분석하여 내 데이터베이스에서 사용합니다.http.Request.Body를 여러 번 읽을 수있는 적절한 방법은 무엇입니까
io.Reader
(또는이 경우 io.ReadCloser
)에서 두 번 이상 읽을 수 없다는 것을 알고 있습니다. 먼저 본문을 읽을 때
그런 다음 예에서 그들은 새로운, 당신은 당신이 그것으로 완료되면, 당신은 원래의 데이터로 구성 요청 본문과 같은 새로운
io.ReadCloser
을 설정할 수 있도록 보관해야한다 : 나는 해결책을 가진 answer to another question 발견 . 따라서 체인에서 진행할 때 다음 처리기가 동일한 본문을 읽을 수 있습니다.
io.ReadCloser
에
http.Request.Body
을 설정
// And now set a new body, which will simulate the same data we read:
r.Body = ioutil.NopCloser(bytes.NewBuffer(body))
는
Body
에서 읽고 다음 내 미들웨어의 각 단계에서 새로운
io.ReadCloser
비싼 것 같습니다 설정. 정확합니까?
덜 지루하고 값 비싸지 않게하기 위해 a solution described here을 사용하여 요청의 값인 Context()
에 파싱 된 바이트 배열을 숨겨 넣습니다. 내가 원하는 때마다 그 바이트의 배열로 이미 나를 기다리고 :
type bodyKey int
const bodyAsBytesKey bodyKey = 0
func newContextWithParsedBody(ctx context.Context, req *http.Request) context.Context {
if req.Body == nil || req.ContentLength <= 0 {
return ctx
}
if _, ok := ctx.Value(bodyAsBytesKey).([]byte); ok {
return ctx
}
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return ctx
}
return context.WithValue(ctx, bodyAsBytesKey, body)
}
func parsedBodyFromContext(ctx context.Context) []byte {
if body, ok := ctx.Value(bodyAsBytesKey).([]byte); ok {
return body
}
return nil
}
나는 주위에 새로운 매번 읽는 것보다 저렴 단일 바이트 배열을 유지하는 것 같은 느낌. 정확합니까? 내가 볼 수없는이 해결책에 함정이 있습니까?
본문을'bytes.Reader' 또는'bytes.Buffer'에 넣는다면 기본적으로 같은 캐시 된 바이트 슬라이스를 유지하는 것입니다. 'ReadAll'로 복사하지 않으려 고하십니까? – JimB
@JimB'ReadAll'은'Body'에서 모든 것을 읽는 가장 간단한 방법이었습니다 –
왜 바이트 슬라이스를 다시 몸에 넣는 것이 비싸다고 생각하니? 그 사본이나 다른 것을 피하려고합니까? 'Reader'와'Closer'에서 단순히 바이트 슬라이스를 감싸는 것은 컨텍스트 메소드보다 비싸지 않습니다. 복사본을 피하려면 간단한 유형을 만들어 본문의 바이트에 직접 액세스하십시오. – JimB