func ReadAllWithLimit()

in transport/httpcommon/httpcommon.go [443:485]


func ReadAllWithLimit(resp *http.Response, limit int64) ([]byte, error) {
	if resp == nil {
		return nil, errors.New("response cannot be nil")
	}
	switch {
	// nothing to read according to the server or limit
	case resp.ContentLength == 0 || limit == 0 || resp.StatusCode == http.StatusNoContent:
		return []byte{}, nil

	// here if the limit is negative, e.g. `-1` it's ignored,
	// limit == 0 is handled above
	case limit > 0 && resp.ContentLength > limit:
		return nil, fmt.Errorf("received Content-Length %d exceeds the set limit %d: %w", resp.ContentLength, limit, ErrResponseLimit)

	// if we know the body length, we can allocate the buffer only once for the most efficient read
	case resp.ContentLength >= 0:
		body := make([]byte, resp.ContentLength)
		_, err := io.ReadFull(resp.Body, body)
		if err != nil {
			return nil, fmt.Errorf("failed to read the response body with a known length %d: %w", resp.ContentLength, err)
		}
		return body, nil

	default:
		// using `bytes.NewBuffer` + `io.Copy` is much faster than `io.ReadAll`
		// see https://github.com/elastic/beats/issues/36151#issuecomment-1931696767
		buf := bytes.NewBuffer(nil)
		var err error
		if limit > 0 {
			_, err = io.Copy(buf, io.LimitReader(resp.Body, limit))
		} else {
			_, err = io.Copy(buf, resp.Body)
		}
		if err != nil {
			return nil, fmt.Errorf("failed to read the response body with unknown length: %w", err)
		}
		body := buf.Bytes()
		if body == nil {
			body = []byte{}
		}
		return body, nil
	}
}