mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-10-09 19:52:30 +02:00
Apply new errors processing to more code parts
This commit is contained in:
@@ -10,8 +10,13 @@ import (
|
|||||||
"golang.org/x/net/publicsuffix"
|
"golang.org/x/net/publicsuffix"
|
||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/config"
|
"github.com/imgproxy/imgproxy/v3/config"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/ierrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type cookieError string
|
||||||
|
|
||||||
|
func (e cookieError) Error() string { return string(e) }
|
||||||
|
|
||||||
type anyCookieJarEntry struct {
|
type anyCookieJarEntry struct {
|
||||||
Name string
|
Name string
|
||||||
Value string
|
Value string
|
||||||
@@ -75,7 +80,7 @@ func JarFromRequest(r *http.Request) (jar http.CookieJar, err error) {
|
|||||||
if !config.CookiePassthroughAll {
|
if !config.CookiePassthroughAll {
|
||||||
if len(config.CookieBaseURL) > 0 {
|
if len(config.CookieBaseURL) > 0 {
|
||||||
if cookieBase, err = url.Parse(config.CookieBaseURL); err != nil {
|
if cookieBase, err = url.Parse(config.CookieBaseURL); err != nil {
|
||||||
return nil, fmt.Errorf("can't parse cookie base URL: %s", err)
|
return nil, ierrors.Wrap(cookieError(fmt.Sprintf("can't parse cookie base URL: %s", err)), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@ package imagedata
|
|||||||
import (
|
import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
@@ -105,7 +104,7 @@ func initDownloading() error {
|
|||||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
redirects := len(via)
|
redirects := len(via)
|
||||||
if redirects >= config.MaxRedirects {
|
if redirects >= config.MaxRedirects {
|
||||||
return fmt.Errorf("stopped after %d redirects", redirects)
|
return newImageTooManyRedirectsError(redirects)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@@ -11,12 +11,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ImageRequestError struct{ error }
|
ImageRequestError struct{ error }
|
||||||
ImageRequstSchemeError string
|
ImageRequstSchemeError string
|
||||||
ImagePartialResponseError string
|
ImagePartialResponseError string
|
||||||
ImageResponseStatusError string
|
ImageResponseStatusError string
|
||||||
ImageRequestCanceledError struct{ error }
|
ImageTooManyRedirectsError string
|
||||||
ImageRequestTimeoutError struct{ error }
|
ImageRequestCanceledError struct{ error }
|
||||||
|
ImageRequestTimeoutError struct{ error }
|
||||||
|
|
||||||
NotModifiedError struct {
|
NotModifiedError struct {
|
||||||
headers map[string]string
|
headers map[string]string
|
||||||
@@ -90,6 +91,18 @@ func newImageResponseStatusError(status int, body string) error {
|
|||||||
|
|
||||||
func (e ImageResponseStatusError) Error() string { return string(e) }
|
func (e ImageResponseStatusError) Error() string { return string(e) }
|
||||||
|
|
||||||
|
func newImageTooManyRedirectsError(n int) error {
|
||||||
|
return ierrors.Wrap(
|
||||||
|
ImageTooManyRedirectsError(fmt.Sprintf("Stopped after %d redirects", n)),
|
||||||
|
1,
|
||||||
|
ierrors.WithStatusCode(http.StatusNotFound),
|
||||||
|
ierrors.WithPublicMessage(msgSourceImageIsUnreachable),
|
||||||
|
ierrors.WithShouldReport(false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ImageTooManyRedirectsError) Error() string { return string(e) }
|
||||||
|
|
||||||
func newImageRequestCanceledError(err error) error {
|
func newImageRequestCanceledError(err error) error {
|
||||||
return ierrors.Wrap(
|
return ierrors.Wrap(
|
||||||
ImageRequestCanceledError{err},
|
ImageRequestCanceledError{err},
|
||||||
|
@@ -185,7 +185,7 @@ func heifReadHldr(r io.Reader, boxDataSize uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(data[8:12], heifPict) {
|
if !bytes.Equal(data[8:12], heifPict) {
|
||||||
return fmt.Errorf("Invalid handler. Expected: pict, actual: %s", data[8:12])
|
return newFormatError("HEIF", fmt.Sprintf("Invalid handler. Expected: pict, actual: %s", data[8:12]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@@ -2,7 +2,6 @@ package options
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -35,11 +34,11 @@ func decodeBase64URL(parts []string) (string, string, error) {
|
|||||||
urlParts := strings.Split(encoded, ".")
|
urlParts := strings.Split(encoded, ".")
|
||||||
|
|
||||||
if len(urlParts[0]) == 0 {
|
if len(urlParts[0]) == 0 {
|
||||||
return "", "", errors.New("Image URL is empty")
|
return "", "", newInvalidURLError("Image URL is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(urlParts) > 2 {
|
if len(urlParts) > 2 {
|
||||||
return "", "", fmt.Errorf("Multiple formats are specified: %s", encoded)
|
return "", "", newInvalidURLError("Multiple formats are specified: %s", encoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(urlParts) == 2 && len(urlParts[1]) > 0 {
|
if len(urlParts) == 2 && len(urlParts[1]) > 0 {
|
||||||
@@ -48,7 +47,7 @@ func decodeBase64URL(parts []string) (string, string, error) {
|
|||||||
|
|
||||||
imageURL, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(urlParts[0], "="))
|
imageURL, err := base64.RawURLEncoding.DecodeString(strings.TrimRight(urlParts[0], "="))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("Invalid url encoding: %s", encoded)
|
return "", "", newInvalidURLError("Invalid url encoding: %s", encoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
return preprocessURL(string(imageURL)), format, nil
|
return preprocessURL(string(imageURL)), format, nil
|
||||||
@@ -61,11 +60,11 @@ func decodePlainURL(parts []string) (string, string, error) {
|
|||||||
urlParts := strings.Split(encoded, "@")
|
urlParts := strings.Split(encoded, "@")
|
||||||
|
|
||||||
if len(urlParts[0]) == 0 {
|
if len(urlParts[0]) == 0 {
|
||||||
return "", "", errors.New("Image URL is empty")
|
return "", "", newInvalidURLError("Image URL is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(urlParts) > 2 {
|
if len(urlParts) > 2 {
|
||||||
return "", "", fmt.Errorf("Multiple formats are specified: %s", encoded)
|
return "", "", newInvalidURLError("Multiple formats are specified: %s", encoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(urlParts) == 2 && len(urlParts[1]) > 0 {
|
if len(urlParts) == 2 && len(urlParts[1]) > 0 {
|
||||||
@@ -74,7 +73,7 @@ func decodePlainURL(parts []string) (string, string, error) {
|
|||||||
|
|
||||||
unescaped, err := url.PathUnescape(urlParts[0])
|
unescaped, err := url.PathUnescape(urlParts[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("Invalid url encoding: %s", encoded)
|
return "", "", newInvalidURLError("Invalid url encoding: %s", encoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
return preprocessURL(unescaped), format, nil
|
return preprocessURL(unescaped), format, nil
|
||||||
@@ -82,7 +81,7 @@ func decodePlainURL(parts []string) (string, string, error) {
|
|||||||
|
|
||||||
func DecodeURL(parts []string) (string, string, error) {
|
func DecodeURL(parts []string) (string, string, error) {
|
||||||
if len(parts) == 0 {
|
if len(parts) == 0 {
|
||||||
return "", "", errors.New("Image URL is empty")
|
return "", "", newInvalidURLError("Image URL is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if parts[0] == urlTokenPlain && len(parts) > 1 {
|
if parts[0] == urlTokenPlain && len(parts) > 1 {
|
||||||
|
25
processing/errors.go
Normal file
25
processing/errors.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package processing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/imgproxy/imgproxy/v3/ierrors"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/imagetype"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
SaveFormatError string
|
||||||
|
)
|
||||||
|
|
||||||
|
func newSaveFormatError(format imagetype.Type) error {
|
||||||
|
return ierrors.Wrap(
|
||||||
|
SaveFormatError(fmt.Sprintf("Can't save %s, probably not supported by your libvips", format)),
|
||||||
|
1,
|
||||||
|
ierrors.WithStatusCode(http.StatusUnprocessableEntity),
|
||||||
|
ierrors.WithPublicMessage("Invalid URL"),
|
||||||
|
ierrors.WithShouldReport(false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e SaveFormatError) Error() string { return string(e) }
|
@@ -3,7 +3,6 @@ package processing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@@ -301,7 +300,7 @@ func ProcessImage(ctx context.Context, imgdata *imagedata.ImageData, po *options
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !vips.SupportsSave(po.Format) {
|
if !vips.SupportsSave(po.Format) {
|
||||||
return nil, fmt.Errorf("Can't save %s, probably not supported by your libvips", po.Format)
|
return nil, newSaveFormatError(po.Format)
|
||||||
}
|
}
|
||||||
|
|
||||||
if po.Format.SupportsAnimationSave() && animated {
|
if po.Format.SupportsAnimationSave() && animated {
|
||||||
|
@@ -109,7 +109,7 @@ func (t transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
if r := req.Header.Get("Range"); len(r) != 0 {
|
if r := req.Header.Get("Range"); len(r) != 0 {
|
||||||
start, end, err := httprange.Parse(r)
|
start, end, err := httprange.Parse(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return httprange.InvalidHTTPRangeResponse(req), err
|
return httprange.InvalidHTTPRangeResponse(req), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if end != 0 {
|
if end != 0 {
|
||||||
|
@@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/config"
|
"github.com/imgproxy/imgproxy/v3/config"
|
||||||
"github.com/imgproxy/imgproxy/v3/httprange"
|
"github.com/imgproxy/imgproxy/v3/httprange"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/ierrors"
|
||||||
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
|
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
|
||||||
"github.com/imgproxy/imgproxy/v3/transport/common"
|
"github.com/imgproxy/imgproxy/v3/transport/common"
|
||||||
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
|
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
|
||||||
@@ -71,7 +72,7 @@ func New() (http.RoundTripper, error) {
|
|||||||
client, err = storage.NewClient(context.Background(), opts...)
|
client, err = storage.NewClient(context.Background(), opts...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Can't create GCS client: %s", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("Can't create GCS client"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return transport{client}, nil
|
return transport{client}, nil
|
||||||
|
@@ -3,7 +3,6 @@ package s3
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -23,6 +22,7 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go-v2/service/sts"
|
"github.com/aws/aws-sdk-go-v2/service/sts"
|
||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/config"
|
"github.com/imgproxy/imgproxy/v3/config"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/ierrors"
|
||||||
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
|
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
|
||||||
"github.com/imgproxy/imgproxy/v3/transport/common"
|
"github.com/imgproxy/imgproxy/v3/transport/common"
|
||||||
)
|
)
|
||||||
@@ -48,7 +48,7 @@ type transport struct {
|
|||||||
func New() (http.RoundTripper, error) {
|
func New() (http.RoundTripper, error) {
|
||||||
conf, err := awsConfig.LoadDefaultConfig(context.Background())
|
conf, err := awsConfig.LoadDefaultConfig(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't load AWS S3 config: %s", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("can't load AWS S3 config"))
|
||||||
}
|
}
|
||||||
|
|
||||||
trans, err := defaultTransport.New(false)
|
trans, err := defaultTransport.New(false)
|
||||||
@@ -90,7 +90,7 @@ func New() (http.RoundTripper, error) {
|
|||||||
|
|
||||||
client, err := createClient(conf, clientOptions)
|
client, err := createClient(conf, clientOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't create S3 client: %s", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("can't create S3 client"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &transport{
|
return &transport{
|
||||||
@@ -248,7 +248,7 @@ func (t *transport) getClient(ctx context.Context, bucket string) (s3Client, err
|
|||||||
|
|
||||||
region, err := s3Manager.GetBucketRegion(ctx, t.defaultClient, bucket)
|
region, err := s3Manager.GetBucketRegion(ctx, t.defaultClient, bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't get bucket region: %s", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("can't get bucket region"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(region) == 0 {
|
if len(region) == 0 {
|
||||||
@@ -265,7 +265,7 @@ func (t *transport) getClient(ctx context.Context, bucket string) (s3Client, err
|
|||||||
|
|
||||||
client, err = createClient(conf, t.clientOptions)
|
client, err = createClient(conf, t.clientOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't create regional S3 client: %s", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("can't create regional S3 client"))
|
||||||
}
|
}
|
||||||
|
|
||||||
t.clientsByRegion[region] = client
|
t.clientsByRegion[region] = client
|
||||||
@@ -295,11 +295,11 @@ func createClient(conf aws.Config, opts []func(*s3.Options)) (s3Client, error) {
|
|||||||
func handleError(req *http.Request, err error) (*http.Response, error) {
|
func handleError(req *http.Request, err error) (*http.Response, error) {
|
||||||
var rerr *awsHttp.ResponseError
|
var rerr *awsHttp.ResponseError
|
||||||
if !errors.As(err, &rerr) {
|
if !errors.As(err, &rerr) {
|
||||||
return nil, err
|
return nil, ierrors.Wrap(err, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rerr.Response == nil || rerr.Response.StatusCode < 100 || rerr.Response.StatusCode == 301 {
|
if rerr.Response == nil || rerr.Response.StatusCode < 100 || rerr.Response.StatusCode == 301 {
|
||||||
return nil, err
|
return nil, ierrors.Wrap(err, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := strings.NewReader(err.Error())
|
body := strings.NewReader(err.Error())
|
||||||
|
@@ -3,7 +3,6 @@ package swift
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -12,6 +11,7 @@ import (
|
|||||||
"github.com/ncw/swift/v2"
|
"github.com/ncw/swift/v2"
|
||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/config"
|
"github.com/imgproxy/imgproxy/v3/config"
|
||||||
|
"github.com/imgproxy/imgproxy/v3/ierrors"
|
||||||
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
|
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
|
||||||
"github.com/imgproxy/imgproxy/v3/transport/common"
|
"github.com/imgproxy/imgproxy/v3/transport/common"
|
||||||
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
|
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
|
||||||
@@ -44,7 +44,7 @@ func New() (http.RoundTripper, error) {
|
|||||||
err = c.Authenticate(ctx)
|
err = c.Authenticate(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("swift authentication error: %s", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("swift authentication error"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return transport{con: c}, nil
|
return transport{con: c}, nil
|
||||||
@@ -91,7 +91,7 @@ func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("error opening object: %v", err)
|
return nil, ierrors.Wrap(err, 0, ierrors.WithPrefix("error opening object"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.ETagEnabled {
|
if config.ETagEnabled {
|
||||||
|
21
vips/bmp.go
21
vips/bmp.go
@@ -9,7 +9,6 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -36,10 +35,6 @@ type bmpHeader struct {
|
|||||||
colorImportant uint32
|
colorImportant uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// errBmpUnsupported means that the input BMP image uses a valid but unsupported
|
|
||||||
// feature.
|
|
||||||
var errBmpUnsupported = errors.New("unsupported BMP image")
|
|
||||||
|
|
||||||
func readUint16(b []byte) uint16 {
|
func readUint16(b []byte) uint16 {
|
||||||
return uint16(b[0]) | uint16(b[1])<<8
|
return uint16(b[0]) | uint16(b[1])<<8
|
||||||
}
|
}
|
||||||
@@ -264,7 +259,7 @@ Loop:
|
|||||||
// If topDown is false, the image rows will be read bottom-up.
|
// If topDown is false, the image rows will be read bottom-up.
|
||||||
func (img *Image) decodeBmpRGB(r io.Reader, width, height, bands int, topDown, noAlpha bool) error {
|
func (img *Image) decodeBmpRGB(r io.Reader, width, height, bands int, topDown, noAlpha bool) error {
|
||||||
if bands != 3 && bands != 4 {
|
if bands != 3 && bands != 4 {
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
imgBands := 3
|
imgBands := 3
|
||||||
@@ -381,13 +376,13 @@ func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if string(b[:2]) != "BM" {
|
if string(b[:2]) != "BM" {
|
||||||
return errors.New("not a BMP image")
|
return newVipsError("not a BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := readUint32(b[10:14])
|
offset := readUint32(b[10:14])
|
||||||
infoLen := readUint32(b[14:18])
|
infoLen := readUint32(b[14:18])
|
||||||
if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen {
|
if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen {
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil {
|
if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil {
|
||||||
@@ -405,14 +400,14 @@ func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
|||||||
height, topDown = -height, true
|
height, topDown = -height, true
|
||||||
}
|
}
|
||||||
if width <= 0 || height <= 0 {
|
if width <= 0 || height <= 0 {
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only support 1 plane and 8, 24 or 32 bits per pixel
|
// We only support 1 plane and 8, 24 or 32 bits per pixel
|
||||||
planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
|
planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
|
||||||
|
|
||||||
if planes != 1 {
|
if planes != 1 {
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
rle := false
|
rle := false
|
||||||
@@ -447,10 +442,10 @@ func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
|||||||
case bpp == 32 && rmask == 0xff0000 && gmask == 0xff00 && bmask == 0xff && amask == 0xff000000:
|
case bpp == 32 && rmask == 0xff0000 && gmask == 0xff00 && bmask == 0xff && amask == 0xff000000:
|
||||||
// Go ahead, it's a regular 32-bit image
|
// Go ahead, it's a regular 32-bit image
|
||||||
default:
|
default:
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
var palette []Color
|
var palette []Color
|
||||||
@@ -497,7 +492,7 @@ func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
|||||||
return img.decodeBmpRGB(r, width, height, 4, topDown, noAlpha)
|
return img.decodeBmpRGB(r, width, height, 4, topDown, noAlpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errBmpUnsupported
|
return newVipsError("unsupported BMP image")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (img *Image) saveAsBmp() (*imagedata.ImageData, error) {
|
func (img *Image) saveAsBmp() (*imagedata.ImageData, error) {
|
||||||
|
@@ -18,7 +18,7 @@ func ColorFromHex(hexcolor string) (Color, error) {
|
|||||||
c := Color{}
|
c := Color{}
|
||||||
|
|
||||||
if !hexColorRegex.MatchString(hexcolor) {
|
if !hexColorRegex.MatchString(hexcolor) {
|
||||||
return c, fmt.Errorf("Invalid hex color: %s", hexcolor)
|
return c, newColorError("Invalid hex color: %s", hexcolor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hexcolor) == 3 {
|
if len(hexcolor) == 3 {
|
||||||
|
@@ -1,13 +1,32 @@
|
|||||||
package vips
|
package vips
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/ierrors"
|
"github.com/imgproxy/imgproxy/v3/ierrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VipsError string
|
type (
|
||||||
|
VipsError string
|
||||||
|
ColorError string
|
||||||
|
)
|
||||||
|
|
||||||
func newVipsError(msg string) error {
|
func newVipsError(msg string) error {
|
||||||
return ierrors.Wrap(VipsError(msg), 2)
|
return ierrors.Wrap(VipsError(msg), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newVipsErrorf(format string, args ...interface{}) error {
|
||||||
|
return ierrors.Wrap(VipsError(fmt.Sprintf(format, args...)), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e VipsError) Error() string { return string(e) }
|
func (e VipsError) Error() string { return string(e) }
|
||||||
|
|
||||||
|
func newColorError(format string, args ...interface{}) error {
|
||||||
|
return ierrors.Wrap(
|
||||||
|
ColorError(fmt.Sprintf(format, args...)),
|
||||||
|
1,
|
||||||
|
ierrors.WithShouldReport(false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ColorError) Error() string { return string(e) }
|
||||||
|
@@ -7,8 +7,6 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/imgproxy/imgproxy/v3/imagedata"
|
"github.com/imgproxy/imgproxy/v3/imagedata"
|
||||||
@@ -43,7 +41,7 @@ func (img *Image) loadIco(data []byte, shrink int, scale float64, pages int) err
|
|||||||
internalType = meta.Format()
|
internalType = meta.Format()
|
||||||
|
|
||||||
if internalType == imagetype.ICO || !SupportsLoad(internalType) {
|
if internalType == imagetype.ICO || !SupportsLoad(internalType) {
|
||||||
return fmt.Errorf("Can't load %s from ICO", internalType)
|
return newVipsErrorf("Can't load %s from ICO", internalType)
|
||||||
}
|
}
|
||||||
|
|
||||||
imgdata := imagedata.ImageData{
|
imgdata := imagedata.ImageData{
|
||||||
@@ -56,7 +54,7 @@ func (img *Image) loadIco(data []byte, shrink int, scale float64, pages int) err
|
|||||||
|
|
||||||
func (img *Image) saveAsIco() (*imagedata.ImageData, error) {
|
func (img *Image) saveAsIco() (*imagedata.ImageData, error) {
|
||||||
if img.Width() > 256 || img.Height() > 256 {
|
if img.Width() > 256 || img.Height() > 256 {
|
||||||
return nil, errors.New("Image dimensions is too big. Max dimension size for ICO is 256")
|
return nil, newVipsError("Image dimensions is too big. Max dimension size for ICO is 256")
|
||||||
}
|
}
|
||||||
|
|
||||||
var ptr unsafe.Pointer
|
var ptr unsafe.Pointer
|
||||||
|
@@ -9,7 +9,6 @@ package vips
|
|||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -69,7 +68,7 @@ func Init() error {
|
|||||||
|
|
||||||
if err := C.vips_initialize(); err != 0 {
|
if err := C.vips_initialize(); err != 0 {
|
||||||
C.vips_shutdown()
|
C.vips_shutdown()
|
||||||
return errors.New("unable to start vips!")
|
return newVipsError("unable to start vips!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable libvips cache. Since processing pipeline is fine tuned, we won't get much profit from it.
|
// Disable libvips cache. Since processing pipeline is fine tuned, we won't get much profit from it.
|
||||||
@@ -355,7 +354,7 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
|
|||||||
case imagetype.TIFF:
|
case imagetype.TIFF:
|
||||||
err = C.vips_tiffload_go(data, dataSize, &tmp)
|
err = C.vips_tiffload_go(data, dataSize, &tmp)
|
||||||
default:
|
default:
|
||||||
return errors.New("Usupported image type to load")
|
return newVipsError("Usupported image type to load")
|
||||||
}
|
}
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
return Error()
|
return Error()
|
||||||
@@ -376,7 +375,7 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
|
|||||||
|
|
||||||
func (img *Image) LoadThumbnail(imgdata *imagedata.ImageData) error {
|
func (img *Image) LoadThumbnail(imgdata *imagedata.ImageData) error {
|
||||||
if imgdata.Type != imagetype.HEIC && imgdata.Type != imagetype.AVIF {
|
if imgdata.Type != imagetype.HEIC && imgdata.Type != imagetype.AVIF {
|
||||||
return errors.New("Usupported image type to load thumbnail")
|
return newVipsError("Usupported image type to load thumbnail")
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmp *C.VipsImage
|
var tmp *C.VipsImage
|
||||||
@@ -428,7 +427,7 @@ func (img *Image) Save(imgtype imagetype.Type, quality int) (*imagedata.ImageDat
|
|||||||
case imagetype.TIFF:
|
case imagetype.TIFF:
|
||||||
err = C.vips_tiffsave_go(img.VipsImage, &ptr, &imgsize, C.int(quality))
|
err = C.vips_tiffsave_go(img.VipsImage, &ptr, &imgsize, C.int(quality))
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Usupported image type to save")
|
return nil, newVipsError("Usupported image type to save")
|
||||||
}
|
}
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
cancel()
|
cancel()
|
||||||
|
Reference in New Issue
Block a user