mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-09-27 03:56:51 +02:00
Add URL replacements
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
### Add
|
||||
- Add `IMGPROXY_URL_REPLACEMENTS` config.
|
||||
|
||||
## [3.17.0] - 2023-05-10
|
||||
### Add
|
||||
|
@@ -127,6 +127,7 @@ var (
|
||||
LastModifiedEnabled bool
|
||||
|
||||
BaseURL string
|
||||
URLReplacements map[*regexp.Regexp]string
|
||||
|
||||
Presets []string
|
||||
OnlyPresets bool
|
||||
@@ -317,6 +318,7 @@ func Reset() {
|
||||
LastModifiedEnabled = false
|
||||
|
||||
BaseURL = ""
|
||||
URLReplacements = make(map[*regexp.Regexp]string)
|
||||
|
||||
Presets = make([]string, 0)
|
||||
OnlyPresets = false
|
||||
@@ -518,6 +520,9 @@ func Configure() error {
|
||||
configurators.Bool(&LastModifiedEnabled, "IMGPROXY_USE_LAST_MODIFIED")
|
||||
|
||||
configurators.String(&BaseURL, "IMGPROXY_BASE_URL")
|
||||
if err := configurators.Replacements(&URLReplacements, "IMGPROXY_URL_REPLACEMENTS"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configurators.StringSlice(&Presets, "IMGPROXY_PRESETS")
|
||||
if err := configurators.StringSliceFile(&Presets, presetsPath); err != nil {
|
||||
|
@@ -221,6 +221,26 @@ func Patterns(s *[]*regexp.Regexp, name string) {
|
||||
}
|
||||
}
|
||||
|
||||
func Replacements(m *map[*regexp.Regexp]string, name string) error {
|
||||
var sm map[string]string
|
||||
|
||||
if err := StringMap(&sm, name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(sm) > 0 {
|
||||
mm := make(map[*regexp.Regexp]string)
|
||||
|
||||
for k, v := range sm {
|
||||
mm[RegexpFromPattern(k)] = v
|
||||
}
|
||||
|
||||
*m = mm
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegexpFromPattern(pattern string) *regexp.Regexp {
|
||||
var result strings.Builder
|
||||
// Perform prefix matching
|
||||
@@ -228,7 +248,7 @@ func RegexpFromPattern(pattern string) *regexp.Regexp {
|
||||
for i, part := range strings.Split(pattern, "*") {
|
||||
// Add a regexp match all without slashes for each wildcard character
|
||||
if i > 0 {
|
||||
result.WriteString("[^/]*")
|
||||
result.WriteString("([^/]*)")
|
||||
}
|
||||
|
||||
// Quote other parts of the pattern
|
||||
|
@@ -406,6 +406,16 @@ imgproxy can process files from OpenStack Object Storage, but this feature is di
|
||||
|
||||
Check out the [Serving files from OpenStack Object Storage](serving_files_from_openstack_swift.md) guide to learn more.
|
||||
|
||||
## Source image URLs
|
||||
|
||||
* `IMGPROXY_BASE_URL`: a base URL prefix that will be added to each source image URL. For example, if the base URL is `http://example.com/images` and `/path/to/image.png` is requested, imgproxy will download the source image from `http://example.com/images/path/to/image.png`. If the image URL already contains the prefix, it won't be added. Default: blank
|
||||
|
||||
* `IMGPROXY_URL_REPLACEMENTS`: a list of `pattern=replacement` pairs, semicolon (`;`) divided. imgproxy will replace source URL prefixes matching the pattern with the corresponding replacement. Wildcards can be included in patterns with `*` to match all characters except `/`. `${N}` in replacement strings will be replaced with wildcard values, where `N` is the number of the wildcard. Examples:
|
||||
* `mys3://=s3://my_bucket/images/` will replace `mys3://image01.jpg` with `s3://my_bucket/images/image01.jpg`
|
||||
* `mys3://*/=s3://my_bucket/${1}/images` will replace `mys3://items/image01.jpg` with `s3://my_bucket/items/images/image01.jpg`
|
||||
|
||||
**📝 Note:** Replacements defined in `IMGPROXY_URL_REPLACEMENTS` are applied before `IMGPROXY_BASE_URL` is added.
|
||||
|
||||
## Metrics
|
||||
|
||||
### New Relic :id=new-relic-metrics
|
||||
@@ -527,7 +537,6 @@ imgproxy can send logs to syslog, but this feature is disabled by default. To en
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* `IMGPROXY_BASE_URL`: a base URL prefix that will be added to each requested image URL. For example, if the base URL is `http://example.com/images` and `/path/to/image.png` is requested, imgproxy will download the source image from `http://example.com/images/path/to/image.png`. If the image URL already contains the prefix, it won't be added. Default: blank
|
||||
* `IMGPROXY_USE_LINEAR_COLORSPACE`: when `true`, imgproxy will process images in linear colorspace. This will slow down processing. Note that images won't be fully processed in linear colorspace while shrink-on-load is enabled (see below).
|
||||
* `IMGPROXY_DISABLE_SHRINK_ON_LOAD`: when `true`, disables shrink-on-load for JPEGs and WebP files. Allows processing the entire image in linear colorspace but dramatically slows down resizing and increases memory usage when working with large images.
|
||||
* `IMGPROXY_STRIP_METADATA`: when `true`, imgproxy will strip all metadata (EXIF, IPTC, etc.) from JPEG and WebP output images. Default: `true`
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -54,6 +55,20 @@ func (s *ProcessingOptionsTestSuite) TestParseBase64URLWithBase() {
|
||||
require.Equal(s.T(), imagetype.PNG, po.Format)
|
||||
}
|
||||
|
||||
func (s *ProcessingOptionsTestSuite) TestParseBase64URLWithReplacement() {
|
||||
config.URLReplacements = map[*regexp.Regexp]string{
|
||||
regexp.MustCompile("^test://([^/]*)/"): "http://images.dev/${1}/dolor/",
|
||||
}
|
||||
|
||||
originURL := "test://lorem/ipsum.jpg?param=value"
|
||||
path := fmt.Sprintf("/size:100:100/%s.png", base64.RawURLEncoding.EncodeToString([]byte(originURL)))
|
||||
po, imageURL, err := ParsePath(path, make(http.Header))
|
||||
|
||||
require.Nil(s.T(), err)
|
||||
require.Equal(s.T(), "http://images.dev/lorem/dolor/ipsum.jpg?param=value", imageURL)
|
||||
require.Equal(s.T(), imagetype.PNG, po.Format)
|
||||
}
|
||||
|
||||
func (s *ProcessingOptionsTestSuite) TestParsePlainURL() {
|
||||
originURL := "http://images.dev/lorem/ipsum.jpg"
|
||||
path := fmt.Sprintf("/size:100:100/plain/%s@png", originURL)
|
||||
@@ -96,6 +111,20 @@ func (s *ProcessingOptionsTestSuite) TestParsePlainURLWithBase() {
|
||||
require.Equal(s.T(), imagetype.PNG, po.Format)
|
||||
}
|
||||
|
||||
func (s *ProcessingOptionsTestSuite) TestParsePlainURLWithReplacement() {
|
||||
config.URLReplacements = map[*regexp.Regexp]string{
|
||||
regexp.MustCompile("^test://([^/]*)/"): "http://images.dev/${1}/dolor/",
|
||||
}
|
||||
|
||||
originURL := "test://lorem/ipsum.jpg"
|
||||
path := fmt.Sprintf("/size:100:100/plain/%s@png", originURL)
|
||||
po, imageURL, err := ParsePath(path, make(http.Header))
|
||||
|
||||
require.Nil(s.T(), err)
|
||||
require.Equal(s.T(), "http://images.dev/lorem/dolor/ipsum.jpg", imageURL)
|
||||
require.Equal(s.T(), imagetype.PNG, po.Format)
|
||||
}
|
||||
|
||||
func (s *ProcessingOptionsTestSuite) TestParsePlainURLEscapedWithBase() {
|
||||
config.BaseURL = "http://images.dev/"
|
||||
|
||||
|
@@ -12,7 +12,11 @@ import (
|
||||
|
||||
const urlTokenPlain = "plain"
|
||||
|
||||
func addBaseURL(u string) string {
|
||||
func preprocessURL(u string) string {
|
||||
for re, repl := range config.URLReplacements {
|
||||
u = re.ReplaceAllString(u, repl)
|
||||
}
|
||||
|
||||
if len(config.BaseURL) == 0 || strings.HasPrefix(u, config.BaseURL) {
|
||||
return u
|
||||
}
|
||||
@@ -43,7 +47,7 @@ func decodeBase64URL(parts []string) (string, string, error) {
|
||||
return "", "", fmt.Errorf("Invalid url encoding: %s", encoded)
|
||||
}
|
||||
|
||||
return addBaseURL(string(imageURL)), format, nil
|
||||
return preprocessURL(string(imageURL)), format, nil
|
||||
}
|
||||
|
||||
func decodePlainURL(parts []string) (string, string, error) {
|
||||
@@ -69,7 +73,7 @@ func decodePlainURL(parts []string) (string, string, error) {
|
||||
return "", "", fmt.Errorf("Invalid url encoding: %s", encoded)
|
||||
}
|
||||
|
||||
return addBaseURL(unescaped), format, nil
|
||||
return preprocessURL(unescaped), format, nil
|
||||
}
|
||||
|
||||
func DecodeURL(parts []string) (string, string, error) {
|
||||
|
Reference in New Issue
Block a user