瀏覽代碼

Adds an option to allows only presets in the URL. (#156)

* Adds an option to allows only presets in the URL.  If it's enabled, only presets can be used, and all other URL formats are disabled. You can allow it to with an env var.

If it's enabled, only presets can be used, and all other URL formats are disabled. You can allow it to with an env var.

* Add parsePathPresets function

Following DarthSim suggestion, I added a parsePathPresets function and remove the code inside parseURLOptions.
Carlos Brando 6 年之前
父節點
當前提交
e071396fd6
共有 5 個文件被更改,包括 83 次插入2 次删除
  1. 4 1
      config.go
  2. 1 0
      docs/configuration.md
  3. 8 0
      docs/presets.md
  4. 30 1
      processing_options.go
  5. 40 0
      processing_options_test.go

+ 4 - 1
config.go

@@ -181,7 +181,8 @@ type config struct {
 
 
 	BaseURL string
 	BaseURL string
 
 
-	Presets presets
+	Presets     presets
+	OnlyPresets bool
 
 
 	WatermarkData    string
 	WatermarkData    string
 	WatermarkPath    string
 	WatermarkPath    string
@@ -232,6 +233,7 @@ var conf = config{
 	SentryRelease:                  fmt.Sprintf("imgproxy/%s", version),
 	SentryRelease:                  fmt.Sprintf("imgproxy/%s", version),
 	FreeMemoryInterval:             10,
 	FreeMemoryInterval:             10,
 	BufferPoolCalibrationThreshold: 1024,
 	BufferPoolCalibrationThreshold: 1024,
+	OnlyPresets:                    false,
 }
 }
 
 
 func init() {
 func init() {
@@ -311,6 +313,7 @@ func init() {
 	conf.Presets = make(presets)
 	conf.Presets = make(presets)
 	presetEnvConfig(conf.Presets, "IMGPROXY_PRESETS")
 	presetEnvConfig(conf.Presets, "IMGPROXY_PRESETS")
 	presetFileConfig(conf.Presets, *presetsPath)
 	presetFileConfig(conf.Presets, *presetsPath)
+	boolEnvConfig(&conf.OnlyPresets, "IMGPROXY_ONLY_PRESETS")
 
 
 	strEnvConfig(&conf.WatermarkData, "IMGPROXY_WATERMARK_DATA")
 	strEnvConfig(&conf.WatermarkData, "IMGPROXY_WATERMARK_DATA")
 	strEnvConfig(&conf.WatermarkPath, "IMGPROXY_WATERMARK_PATH")
 	strEnvConfig(&conf.WatermarkPath, "IMGPROXY_WATERMARK_PATH")

+ 1 - 0
docs/configuration.md

@@ -111,6 +111,7 @@ There are two ways to define presets:
 ##### Using an environment variable
 ##### Using an environment variable
 
 
 * `IMGPROXY_PRESETS`: set of preset definitions, comma-divided. Example: `default=resizing_type:fill/enlarge:1,sharp=sharpen:0.7,blurry=blur:2`. Default: blank.
 * `IMGPROXY_PRESETS`: set of preset definitions, comma-divided. Example: `default=resizing_type:fill/enlarge:1,sharp=sharpen:0.7,blurry=blur:2`. Default: blank.
+* `IMGPROXY_ONLY_PRESETS`: disable all URL formats but presets. In this case, you always need to inform a valid preset. Example: `http://imgproxy.example.com/unsafe/thumbnail/plain/http://example.com/images/curiosity.jpg@png`
 
 
 ##### Using a command line argument
 ##### Using a command line argument
 
 

+ 8 - 0
docs/presets.md

@@ -21,3 +21,11 @@ Read how to specify your presets with imgproxy in the [Configuration](./configur
 ### Default preset
 ### Default preset
 
 
 A preset named `default` will be applied to each image. Useful in case you want your default processing options to be different from the imgproxy default ones.
 A preset named `default` will be applied to each image. Useful in case you want your default processing options to be different from the imgproxy default ones.
+
+### Only presets
+
+If you set `IMGPROXY_ONLY_PRESETS` as `true`, a preset is obligatory, and all other URL formats are disabled.
+
+In this case, you always need to inform a preset in your URLs without the `preset` or `pr` statement. Example: `http://imgproxy.example.com/AfrOrF3gWeDA6VOlDG4TzxMv39O7MXnF4CXpKUwGqRM/thumbnail/aHR0cDovL2V4YW1w/bGUuY29tL2ltYWdl/cy9jdXJpb3NpdHku/anBn.png`
+
+It's possible to use more than one preset separing them with `:` like `thumbnail:gray`.

+ 30 - 1
processing_options.go

@@ -803,6 +803,33 @@ func parsePathAdvanced(parts []string, headers *processingHeaders) (string, *pro
 	return url, po, nil
 	return url, po, nil
 }
 }
 
 
+func parsePathPresets(parts []string, headers *processingHeaders) (string, *processingOptions, error) {
+	po, err := defaultProcessingOptions(headers)
+	if err != nil {
+		return "", po, err
+	}
+
+	presets := strings.Split(parts[0], ":")
+	urlParts := parts[1:]
+
+	if err := applyPresetOption(po, presets); err != nil {
+		return "", nil, err
+	}
+
+	url, extension, err := decodeURL(urlParts)
+	if err != nil {
+		return "", po, err
+	}
+
+	if len(extension) > 0 {
+		if err := applyFormatOption(po, []string{extension}); err != nil {
+			return "", po, err
+		}
+	}
+
+	return url, po, nil
+}
+
 func parsePathBasic(parts []string, headers *processingHeaders) (string, *processingOptions, error) {
 func parsePathBasic(parts []string, headers *processingHeaders) (string, *processingOptions, error) {
 	var err error
 	var err error
 
 
@@ -875,7 +902,9 @@ func parsePath(ctx context.Context, r *http.Request) (context.Context, error) {
 	var po *processingOptions
 	var po *processingOptions
 	var err error
 	var err error
 
 
-	if _, ok := resizeTypes[parts[1]]; ok {
+	if conf.OnlyPresets {
+		imageURL, po, err = parsePathPresets(parts[1:], headers)
+	} else if _, ok := resizeTypes[parts[1]]; ok {
 		imageURL, po, err = parsePathBasic(parts[1:], headers)
 		imageURL, po, err = parsePathBasic(parts[1:], headers)
 	} else {
 	} else {
 		imageURL, po, err = parsePathAdvanced(parts[1:], headers)
 		imageURL, po, err = parsePathAdvanced(parts[1:], headers)

+ 40 - 0
processing_options_test.go

@@ -561,6 +561,46 @@ func (s *ProcessingOptionsTestSuite) TestParsePathSignedInvalid() {
 	assert.Equal(s.T(), errInvalidSignature.Error(), err.Error())
 	assert.Equal(s.T(), errInvalidSignature.Error(), err.Error())
 }
 }
 
 
+func (s *ProcessingOptionsTestSuite) TestParsePathOnlyPresets() {
+	conf.OnlyPresets = true
+	conf.Presets["test1"] = urlOptions{
+		"blur": []string{"0.2"},
+	}
+	conf.Presets["test2"] = urlOptions{
+		"quality": []string{"50"},
+	}
+
+	req := s.getRequest("http://example.com/unsafe/test1:test2/plain/http://images.dev/lorem/ipsum.jpg")
+
+	ctx, err := parsePath(context.Background(), req)
+
+	require.Nil(s.T(), err)
+
+	po := getProcessingOptions(ctx)
+	assert.Equal(s.T(), float32(0.2), po.Blur)
+	assert.Equal(s.T(), 50, po.Quality)
+}
+
+func (s *ProcessingOptionsTestSuite) TestParseBase64URLOnlyPresets() {
+	conf.OnlyPresets = true
+	conf.Presets["test1"] = urlOptions{
+		"blur": []string{"0.2"},
+	}
+	conf.Presets["test2"] = urlOptions{
+		"quality": []string{"50"},
+	}
+
+	imageURL := "http://images.dev/lorem/ipsum.jpg?param=value"
+	req := s.getRequest(fmt.Sprintf("http://example.com/unsafe/test1:test2/%s.png", base64.RawURLEncoding.EncodeToString([]byte(imageURL))))
+
+	ctx, err := parsePath(context.Background(), req)
+
+	require.Nil(s.T(), err)
+
+	po := getProcessingOptions(ctx)
+	assert.Equal(s.T(), float32(0.2), po.Blur)
+	assert.Equal(s.T(), 50, po.Quality)
+}
 func TestProcessingOptions(t *testing.T) {
 func TestProcessingOptions(t *testing.T) {
 	suite.Run(t, new(ProcessingOptionsTestSuite))
 	suite.Run(t, new(ProcessingOptionsTestSuite))
 }
 }