1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-02-12 11:46:10 +02:00

Fix treating percent-encoded symbols in s3://, gcs://, abs://, and swift:// URLs

This commit is contained in:
DarthSim 2024-06-11 19:12:07 +03:00
parent cb32e71788
commit c01158977c
7 changed files with 43 additions and 14 deletions

View File

@ -9,7 +9,7 @@
### Changed
- Automatically add `http://` scheme to the `IMGPROXY_S3_ENDPOINT` value if it has no scheme.
- Trim redundant slashes in the S3 object key.
- Trim redundant slashes in the S3, GCS, ABS, and Swift object keys.
- Rename `IMGPROXY_WRITE_TIMEOUT` to `IMGPROXY_TIMEOUT`. The old name is deprecated but still supported.
- Rename `IMGPROXY_READ_TIMEOUT` to `IMGPROXY_READ_REQUEST_TIMEOUT`. The old name is deprecated but still supported.
- (pro) Allow specifying [gradient](https://docs.imgproxy.net/latest/usage/processing#gradient) direction as an angle in degrees.
@ -17,6 +17,7 @@
### Fix
- Fix HEIC/AVIF dimension limit handling.
- Fix SVG detection when the root element has a namespace.
- Fix treating percent-encoded symbols in `s3://`, `gcs://`, `abs://`, and `swift://` URLs.
- (pro) Fix style injection to SVG.
- (pro) Fix video tiles generation when the video's SAR is not `1`.

View File

@ -19,6 +19,7 @@ import (
"github.com/imgproxy/imgproxy/v3/config"
"github.com/imgproxy/imgproxy/v3/httprange"
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
"github.com/imgproxy/imgproxy/v3/transport/common"
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
)
@ -83,8 +84,7 @@ func New() (http.RoundTripper, error) {
}
func (t transport) RoundTrip(req *http.Request) (*http.Response, error) {
container := req.URL.Host
key := strings.TrimPrefix(req.URL.Path, "/")
container, key := common.GetBucketAndKey(req.URL)
if len(container) == 0 || len(key) == 0 {
body := strings.NewReader("Invalid ABS URL: container name or object key is empty")

View File

@ -0,0 +1,25 @@
package common
import (
"net/url"
"strings"
)
func GetBucketAndKey(u *url.URL) (bucket, key string) {
bucket = u.Host
// We can't use u.Path here because `url.Parse` unescapes the original URL's path.
// So we have to use `u.RawPath` if it's available.
// If it is not available, then `u.EscapedPath()` is the same as the original URL's path
// before `url.Parse`.
// See: https://cs.opensource.google/go/go/+/refs/tags/go1.22.4:src/net/url/url.go;l=680
if len(u.RawPath) > 0 {
key = u.RawPath
} else {
key = u.EscapedPath()
}
key = strings.TrimLeft(key, "/")
return
}

View File

@ -15,6 +15,7 @@ import (
"github.com/imgproxy/imgproxy/v3/config"
"github.com/imgproxy/imgproxy/v3/httprange"
"github.com/imgproxy/imgproxy/v3/transport/common"
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
)
@ -29,10 +30,13 @@ func New() transport {
func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
header := make(http.Header)
f, err := t.fs.Open(req.URL.Path)
_, path := common.GetBucketAndKey(req.URL)
path = "/" + path
f, err := t.fs.Open(path)
if err != nil {
if os.IsNotExist(err) {
return respNotFound(req, fmt.Sprintf("%s doesn't exist", req.URL.Path)), nil
return respNotFound(req, fmt.Sprintf("%s doesn't exist", path)), nil
}
return nil, err
}
@ -43,7 +47,7 @@ func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error)
}
if fi.IsDir() {
return respNotFound(req, fmt.Sprintf("%s is directory", req.URL.Path)), nil
return respNotFound(req, fmt.Sprintf("%s is directory", path)), nil
}
statusCode := 200
@ -75,7 +79,7 @@ func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error)
default:
if config.ETagEnabled {
etag := BuildEtag(req.URL.Path, fi)
etag := BuildEtag(path, fi)
header.Set("ETag", etag)
}

View File

@ -17,6 +17,7 @@ import (
"github.com/imgproxy/imgproxy/v3/config"
"github.com/imgproxy/imgproxy/v3/httprange"
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
"github.com/imgproxy/imgproxy/v3/transport/common"
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
)
@ -77,8 +78,7 @@ func New() (http.RoundTripper, error) {
}
func (t transport) RoundTrip(req *http.Request) (*http.Response, error) {
bucket := req.URL.Host
key := strings.TrimPrefix(req.URL.Path, "/")
bucket, key := common.GetBucketAndKey(req.URL)
if len(bucket) == 0 || len(key) == 0 {
body := strings.NewReader("Invalid GCS URL: bucket name or object key is empty")

View File

@ -24,6 +24,7 @@ import (
"github.com/imgproxy/imgproxy/v3/config"
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
"github.com/imgproxy/imgproxy/v3/transport/common"
)
type s3Client interface {
@ -102,8 +103,7 @@ func New() (http.RoundTripper, error) {
}
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
bucket := req.URL.Host
key := strings.TrimLeft(req.URL.Path, "/")
bucket, key := common.GetBucketAndKey(req.URL)
if len(bucket) == 0 || len(key) == 0 {
body := strings.NewReader("Invalid S3 URL: bucket name or object key is empty")

View File

@ -13,6 +13,7 @@ import (
"github.com/imgproxy/imgproxy/v3/config"
defaultTransport "github.com/imgproxy/imgproxy/v3/transport"
"github.com/imgproxy/imgproxy/v3/transport/common"
"github.com/imgproxy/imgproxy/v3/transport/notmodified"
)
@ -50,9 +51,7 @@ func New() (http.RoundTripper, error) {
}
func (t transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
// Users should have converted the object storage URL in the format of swift://{container}/{object}
container := req.URL.Host
objectName := strings.TrimPrefix(req.URL.Path, "/")
container, objectName := common.GetBucketAndKey(req.URL)
if len(container) == 0 || len(objectName) == 0 {
body := strings.NewReader("Invalid Swift URL: container name or object name is empty")