Browse Source

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 years ago
parent
commit
e071396fd6
5 changed files with 83 additions and 2 deletions
  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
 
-	Presets presets
+	Presets     presets
+	OnlyPresets bool
 
 	WatermarkData    string
 	WatermarkPath    string
@@ -232,6 +233,7 @@ var conf = config{
 	SentryRelease:                  fmt.Sprintf("imgproxy/%s", version),
 	FreeMemoryInterval:             10,
 	BufferPoolCalibrationThreshold: 1024,
+	OnlyPresets:                    false,
 }
 
 func init() {
@@ -311,6 +313,7 @@ func init() {
 	conf.Presets = make(presets)
 	presetEnvConfig(conf.Presets, "IMGPROXY_PRESETS")
 	presetFileConfig(conf.Presets, *presetsPath)
+	boolEnvConfig(&conf.OnlyPresets, "IMGPROXY_ONLY_PRESETS")
 
 	strEnvConfig(&conf.WatermarkData, "IMGPROXY_WATERMARK_DATA")
 	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
 
 * `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
 

+ 8 - 0
docs/presets.md

@@ -21,3 +21,11 @@ Read how to specify your presets with imgproxy in the [Configuration](./configur
 ### 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.
+
+### 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
 }
 
+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) {
 	var err error
 
@@ -875,7 +902,9 @@ func parsePath(ctx context.Context, r *http.Request) (context.Context, error) {
 	var po *processingOptions
 	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)
 	} else {
 		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())
 }
 
+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) {
 	suite.Run(t, new(ProcessingOptionsTestSuite))
 }