#概要
ginで不確定なjosnをinterfaceに変換する際、一定サイズを超えると変換できない状態になった。
###コード
func SAmple(c *gin.Context) {
~~~
//bodyを取得
buf := make([]byte, 1028)
n, _ := c.Request.Body.Read(buf)
body := string(buf[0:n])
//bodyをmapに変換
var json_parse map[string]interface{}
err := json.Unmarshal([]byte(b), &json_parse)
~~~
}
c.Request.Body.Readでバイトスライスにボディを格納してstring形に変換していますが、
jsonのサイズが一定値を超えるとパースできなくなりました。
私の環境ではnが2575で上限になりそれ以降のリクエストボディがbodyに格納されずjson.Unmarssamlでエラーになっていました。
##修正前に
Webサーバがbodyを制限なく受け入れるとbodyサイズだけサーバのメモリが消費されるため、
大きなbodyを送信しサーバをダウンさせるセキュリティホールになります。
そのため、API側で受け取れるbodyに上限を設けることは、Webに公開するAPIの場合必須になります。
その点は注意したうえで実装してください。
##修正後
func SAmple(c *gin.Context) {
~~~
//bodyを取得
var bodyBytes []byte
if c.Request.Body != nil {
bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
}
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
bodyString := string(bodyBytes)
//変換
var json_parse map[string]interface{}
err := json.Unmarshal([]byte(b), &json_parse)
~~~
}
ioutil.ReadAllですべてのbodyを読み込めるので問題なくjsonをinterfaceへ変換できます。
#まとめ
c.Request.Body.Read(buf)にはサイズに上限がある。
全部読み込みたい場合は、ioutil.ReadAll(c.Request.Body)で読み込みましょう
ありがとうございました。