2 回答

TA貢獻1827條經(jīng)驗 獲得超4個贊
可能具有欺騙性的是,壓縮后的大小可能明顯小于允許的大?。梢曰蚰M幚淼拇笮。?。在您的示例中,輸入約為 1 MB,而未壓縮的大小約為 1 GB。
在讀取未壓縮的數(shù)據(jù)時,您應該在達到合理的限制后停止。為了輕松做到這一點,您可以使用io.LimitReader()
可以指定要讀取的最大字節(jié)數(shù)的位置。是的,您必須包裝解壓縮的流,而不是原始的壓縮流。
這是一個示例:
limited?:=?io.LimitReader(fz,?2*1024*1024) s,?err?:=?ioutil.ReadAll(limited)
上面的示例將可讀數(shù)據(jù)限制為 2 MB。當解壓后的數(shù)據(jù)超過這個數(shù)時會發(fā)生什么?返回io.Reader
的io.LimitReader()
(順便說一句io.LimitedReader
)將報告io.EOF
。這可以保護您的服務器免受攻擊,但可能不是處理攻擊的最佳方法。
由于您提到這是針對 REST API 的,因此更適合的解決方案是類似的http.MaxBytesReader()
.?這會包裝傳遞的讀取器以讀取直到給定的限制,如果達到了限制,它將返回一個錯誤,并將錯誤發(fā)送回 HTTP 客戶端,并關閉底層的讀取關閉器。如果默認行為http.MaxBytesReader()
不適合你,檢查它的來源,復制它并修改它,相對簡單。根據(jù)您的需要進行調(diào)整。
另請注意,您不應將所有內(nèi)容(未壓縮的數(shù)據(jù))讀入內(nèi)存。您可以傳遞“有限讀取器”,json.NewDecoder()
在解碼輸入 JSON 時將從給定讀取器讀取數(shù)據(jù)。當然如果通過的受限閱讀器報錯,解碼就會失敗。

TA貢獻1842條經(jīng)驗 獲得超13個贊
不要將所有內(nèi)容讀入內(nèi)存。如果可能的話,對流進行操作。在您的示例中這是 100% 可能的:
func ReadGzFile(filename string) (io.ReadCloser, error) {
fi, err := os.Open(filename)
if err != nil {
return nil, err
}
return gzip.NewReader(fi)
}
func main() {
b, err := ReadGzFile("test.gzip")
if err != nil {
log.Println(err)
}
defer b.Close()
var dat map[string]interface{}
if err := json.NewDecoder(b).Decode(&dat); err != nil {
panic(err)
}
fmt.Println(dat)
}
此Decode方法具有忽略第一個有效 JSON 對象之后流中的任何垃圾的副作用(可能需要也可能不需要)。就您而言,這似乎是一個好處。在某些情況下,可能并非如此。
- 2 回答
- 0 關注
- 164 瀏覽
添加回答
舉報