Web/GoLang

Golang: io.ReadWriter 의 content 를 날려먹지 않는 법

벨포트조던 2022. 10. 7.
반응형

개요

원문링크: https://medium.com/@xoen/golang-read-from-an-io-readwriter-without-loosing-its-content-2c6911805361

 

 

이런 상황을 가정해보자

 

1) HTTP Request 를 받았다.

2) Request 의 body 내용을 보고  이런저런 처리를 한 다음에

3) 본격적인 처리를 하는 Controller 에게 Request body 를 넘겨주고 싶다.

 

 

시도와 낭패

 

Request body  byte string 으로 읽어내려면 ioutil.ReadAll()  쓰면 된다.

 

var bodyBytes []byte
if body != nil {
  bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
}
bodyString := string(bodyBytes)

 

그런데 다시 한 번, c.Request.Body 의 내용을 읽으려 하면 아무것도 없다는 것에 당황하게 된다.

Request.Body 는 io.ReadCloser type 이며 이 타입은 마치 물을 담은 생수통과 같다.

 

1) ioutil.ReadAll() 이라는 밸브로 일단 물을 뽑아내고 나면

2) 생수통은 텅텅 비게 되는 것이다.

 

 

해법

 

해법을 알면 간단하다.

 

1) 일단 ioutil.ReadAll()  사용하면 Reqeust.Body 라는 생수통은 텅텅 비게 된다.

2) 텅텅  생수통인 c.Reqeust.Body 

- 방금 받은 물인 bodyBytes  bytes.NewBuffer()  이용하여  새로운 버퍼를 생성한 다음

- ioutil.NopCloser()  ReadCloser  만들어 넣어주면 된다.

3) 그리곤 남아있는, 받아놓은 물이 bodyBytes  하고픈 일을 하면 된다.

 

 

// Read the content
var bodyBytes []byte
if c.Request.Body != nil {
  bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
}
// Restore the io.ReadCloser to its original state
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
// Use the content
bodyString := string(bodyBytes)

 

(참고)
NewBuffer creates and initializes a new Buffer using buf as its initial contents. The new Buffer takes ownership of buf, and the caller should not use buf after this call. NewBuffer is intended to prepare a Buffer to read existing data. It can also be used to size the internal buffer for writing. To do that, buf should have the desired capacity but a length of zero.
In most cases, new(Buffer) (or just declaring a Buffer variable) is sufficient to initialize a Buffer.

 

 

실전 예시

 

원문 포스팅을 구글링으로 찾게  코드이다.

 

1) req.Body  내용을 ioutil.ReadAll()  읽어낸 다음

2) 비어 있는 req.Body  ioutil.NopCloser(bytes.NewBuffer())  채워놓고

3) 덩그러니 남은 bodyBytes  원하는 작업을 하고 있다.

 

 

 

 
반응형

댓글