read.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package imagedata
  2. import (
  3. "bytes"
  4. "context"
  5. "io"
  6. "github.com/imgproxy/imgproxy/v3/bufpool"
  7. "github.com/imgproxy/imgproxy/v3/bufreader"
  8. "github.com/imgproxy/imgproxy/v3/config"
  9. "github.com/imgproxy/imgproxy/v3/ierrors"
  10. "github.com/imgproxy/imgproxy/v3/imagemeta"
  11. "github.com/imgproxy/imgproxy/v3/security"
  12. )
  13. var ErrSourceImageTypeNotSupported = ierrors.New(422, "Source image type not supported", "Invalid source image")
  14. var downloadBufPool *bufpool.Pool
  15. func initRead() {
  16. downloadBufPool = bufpool.New("download", config.Concurrency, config.DownloadBufferSize)
  17. }
  18. func readAndCheckImage(r io.Reader, contentLength int, secopts security.Options) (*ImageData, error) {
  19. if err := security.CheckFileSize(contentLength, secopts); err != nil {
  20. return nil, err
  21. }
  22. buf := downloadBufPool.Get(contentLength, false)
  23. cancel := func() { downloadBufPool.Put(buf) }
  24. r = security.LimitFileSize(r, secopts)
  25. br := bufreader.New(r, buf)
  26. meta, err := imagemeta.DecodeMeta(br)
  27. if err != nil {
  28. buf.Reset()
  29. cancel()
  30. if err == imagemeta.ErrFormat {
  31. return nil, ErrSourceImageTypeNotSupported
  32. }
  33. return nil, checkTimeoutErr(err)
  34. }
  35. if err = security.CheckDimensions(meta.Width(), meta.Height(), 1, secopts); err != nil {
  36. buf.Reset()
  37. cancel()
  38. return nil, err
  39. }
  40. if contentLength > buf.Cap() {
  41. buf.Grow(contentLength - buf.Len())
  42. }
  43. if err = br.Flush(); err != nil {
  44. cancel()
  45. return nil, checkTimeoutErr(err)
  46. }
  47. return &ImageData{
  48. Data: buf.Bytes(),
  49. Type: meta.Format(),
  50. cancel: cancel,
  51. }, nil
  52. }
  53. func BorrowBuffer() (*bytes.Buffer, context.CancelFunc) {
  54. buf := downloadBufPool.Get(0, false)
  55. cancel := func() { downloadBufPool.Put(buf) }
  56. return buf, cancel
  57. }