Skip to content
This repository

Added route options to pass width and height in URI (for dynamic image sizes) #42

Closed
wants to merge 7 commits into from

7 participants

Anton Babenko Lukas Kahwe Smith Vincent Terraillon Miha Vrhovnik Jordi Boggiano Marc Weistroff Dan
Anton Babenko

No description provided.

Lukas Kahwe Smith
Owner

interesting .. i guess this also serves as an example of #3

one note: this can be an attack vector to make it easier to do DOS attacks, since even with caching it could be possible to generate an endless number of images that will eat CPU and HD space. maybe this should be noted in the docs too.

aside from this i would also love to get an example of how to make such dynamic configuration possible on the server side. aka storing the dynamic configuration with the image somewhere and reading it out in the controller and then configuring the filters dynamically. this would prevent the above mentioned DOS attack, while giving similar flexibility at least for some use cases.

Anton Babenko

As a protection against DOS attacks I was thinking to add a hash key as a GET parameter. Like this:
http://localhost/cache/my_thumb/140x250/image.jpg?hash=abcd . If hash value (based on secret, width, heightt) is correct then image can be resized/stored/viewed, if not then image can only be viewed (if image has been already created).

Regarding server-side dynamic configuration. It doesn't look like it is possible to access private $filters from FilterConfiguration class from controller, so I have to extend that class and overload get() method and replace values if filter name is what I need. Not nice I know, but works. :)

public function get($filter)
  {
    $filterData = parent::get($filter);

    if ($filter == "custom")
    {
      $filterData["filters"]["thumbnail"] = array(
        "size" => array((int)$this->request->get('width'), (int)$this->request->get('height')),
        "mode" => "inset"
      );
    }

    return $filterData;
  }
Lukas Kahwe Smith
Owner

for the DOS protection i guess something like that could be viable. we could also think about some tool that scans for image sizes in templates and "warms" the cache.

for the server side config. in the controller you would have to inject the FilterConfiguration to be abel to dynamically modify the settings.

Anton Babenko

Thanks Lukas. I made it to work with hash protection via URI and for this I used to inject FilterConfiguration into controller. Does it look ok? Going to work on twig extension for dynamic image sizes tomorrow.

Imagine/Cache/CacheManager.php
@@ -114,6 +114,12 @@ private function getResolver($filter)
114 114
     public function getBrowserPath($targetPath, $filter, $absolute = false)
115 115
     {
116 116
         $params = array('path' => ltrim($targetPath, '/'));
  117
+        
  118
+        // Merge params passed from template dynamically
  119
+        if (is_array($filter)) {
  120
+          $params = array_merge($params, $filter["params"]);
1
Lukas Kahwe Smith Owner

indention is off here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Imagine/Filter/FilterConfiguration.php
@@ -41,4 +43,55 @@ public function set($filter, array $config)
41 43
     {
42 44
         return $this->filters[$filter] = $config;
43 45
     }
  46
+
  47
+    /**
  48
+     * Update filter configuration with values from Request object
  49
+     * 
  50
+     * @param string $filter
  51
+     * @param Request $request
  52
+     *
  53
+     * @return array
  54
+     */
  55
+    public function updateFromRequest($filter, Request $request)
  56
+    {
  57
+        $filterConfiguration = $this->get($filter);
  58
+        
  59
+        if (!empty($filterConfiguration['route']))
1
Lukas Kahwe Smith Owner

the opening { are incorrect in this method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Imagine/Filter/FilterConfiguration.php
((27 lines not shown))
  69
+            $filterConfiguration = $this->set($filter, $filterConfiguration);
  70
+        }
  71
+        
  72
+        return $filterConfiguration;
  73
+    }
  74
+
  75
+    /**
  76
+     * Verify if provided access key (hash) is valid?
  77
+     * 
  78
+     * @param string $filter
  79
+     * @param string $path
  80
+     * @param Request $request
  81
+     *
  82
+     * @return boolean
  83
+     */
  84
+    public function isValidAccessKey($filter, $path, Request $request) {
1
Lukas Kahwe Smith Owner

opening bracket is off

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Imagine/Filter/FilterConfiguration.php
((38 lines not shown))
  80
+     * @param Request $request
  81
+     *
  82
+     * @return boolean
  83
+     */
  84
+    public function isValidAccessKey($filter, $path, Request $request) {
  85
+        
  86
+        $filterConfiguration = $this->get($filter);
  87
+        
  88
+        if (!isset($filterConfiguration["route"]["hash"]) || false === $filterConfiguration["route"]["hash"]) {
  89
+            return true;
  90
+        }
  91
+        
  92
+        $validHash = substr(md5($request->get('width') . "|" . $request->get('height') . "|" . $path), 0, 4);
  93
+        
  94
+        return $request->get('hash') == $validHash;
  95
+        
1
Lukas Kahwe Smith Owner

remove the extra empty line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Lukas Kahwe Smith
Owner

hmm i think i would prefer to keep the methods you added out of FilterConfiguration and instead letting users optionally put the code into their controllers if they need this feature. So the given code would be added into the README instead.

the other option would be to provide an extended FilterConfiguration class and to make it possible to choose between the basic and this extended version.

i am not quite sure .. need to think about it. ok?

Lukas Kahwe Smith
Owner

still pondering .. @mheleniak, @LouTerrailloune .. what do you guys think?

Vincent Terraillon

I really like the possibility to add custom parameters to the route (but I think the config is a bit confusing: patternshould be name pattern_suffix)

The whole dynamic resizing feature seams to be a very specific use case which could be implemented with custom controller/cache_manager.

Anton Babenko

Agree with renaming to pattern_suffix (will do when we agree on other things), but disagree that my dynamic resizing is a very specific use case.

Vincent Terraillon

I even think everything related to the 'size' of the image is specific. The goal of this bundle is (correct me if I'm wrong): apply a set of Imagine filters to a source image, and save it somewhere in the web root folder so that it is sent directly by the webserver on subsequent access.

You can, for exemple, have a filter set that just watermark the picture (without resizing it). This is the final developper that decide to 'resize' it's pictures or not.

May be another way of doing this is to find a way to dynamicly add filter_set definitions (through a DB and a backoffice), to allow the final user to define filter_sets.

Lukas Kahwe Smith lsmith77 commented on the diff December 19, 2011
Imagine/Filter/FilterConfiguration.php
((35 lines not shown))
  77
+     * @param Request $request
  78
+     *
  79
+     * @return boolean
  80
+     */
  81
+    public function isValidAccessKey($filter, $path, Request $request)
  82
+    {
  83
+
  84
+        $filterConfiguration = $this->get($filter);
  85
+
  86
+        if (!isset($filterConfiguration["route"]["hash"]) || false === $filterConfiguration["route"]["hash"]) {
  87
+            return true;
  88
+        }
  89
+
  90
+        $validHash = substr(md5($request->get('width') . "|" . $request->get('height') . "|" . $path), 0, 4);
  91
+
  92
+        return $request->get('hash') == $validHash;
3
Lukas Kahwe Smith Owner

hmm i am not sure what you are validating here .. it would still allow someone to generate urls with arbitrary width/height. i guess you need to add some server secret.

I made it in the easiest and fastest way, but in order to use server secret I think it is better to introduce hash validation service, which should be configured in imagine.xml.

Lukas Kahwe Smith Owner

yeah .. which is another reason to move this out of this class .. and instead make it an optional feature that can be used from the controller

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Deleted user

The content you are editing has changed. Reload the page and try again.

Hi. I completly agree with the following sentences:

one note: this can be an attack vector to make it easier to do DOS attacks, since even with caching it could be possible to generate an endless number of images that will eat CPU and HD space. maybe this should be noted in the docs too.

and

You can, for exemple, have a filter set that just watermark the picture (without resizing it). This is the final developper that decide to 'resize' it's pictures or not.

What I can add... IMHO focusing only on width and height is a step back in a functionality. I also don't see an use case for specifing so many dimensions that it needs to go in the templates and not the config (seems like bad design to me).

What's more - what's the benefit in writing:

<img src="{{ '/relative/path/to/image.jpg' | imagine_filter(['my_thumb', 200, 300]) }}" />

(with all the code complexity & hashing needs)

vs

<img src="{{ '/relative/path/to/image.jpg' | imagine_filter(['my_thumb_200x300']) }}" />

(which can be easily configured right now)

what we are trying to achive?

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Lukas Kahwe Smith
Owner

the goal is to be able to let the designer determine the size without having to hardcode the option inside a specific filter. i see this more as a way to define filters dynamically, but imho there is no way to make this sufficiently flexible out of the box without adding a ton of code, so if at all i think we should figure out how to let users do this inside custom controllers.

Deleted user

The content you are editing has changed. Reload the page and try again.

I still don't see any benefit and a lot of complexity. I am -1 for now.

This for example could be implemented via custom Twig function or filter which modifies URL, custom route which handles this URL, custom controller which modifies filter configuration according to the URL and passes request to ImagineController. Right? This way we don't add custom implementation to the repo and you got what you need.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Deleted user

The content you are editing has changed. Reload the page and try again.

... so if at all i think we should figure out how to let users do this inside custom controllers.

  1. Define custom route to fit your needs.
  2. Create custom Twig function or use path() to pass arguments.
  3. Define custom controller which handles the route
  4. In the controller grab liip_imagine.filter.configuration service change the filter definition and pass the request to ImagineController.

IMHO this can't be more flexible :)

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Lukas Kahwe Smith
Owner

so to me what makes sense to add to core is the following:
1) a way to add additional route parameters
2) these additional route parameters should be secured via some hash
3) this hash generation should be generated inside the template extension/helpers
4) add a README entry about how to use them to dynamically adjust the FilterConfiguration inside the a custom Controller

Vincent Terraillon

I think only 1) (additionnal route params) is needed, none with @mheleniak suggestion about creating another route and forwarding.

Lukas Kahwe Smith
Owner

well 2) and 3) are need because otherwise it is hard for the dev to be able to determine if the dynamic parameters are not a DOS attack. then again, maybe there is another bundle that covers this ..

afaik https://github.com/nelmio/NelmioSecurityBundle includes cookie signing, maybe it would make sense to expand it to GET parameter signing ..

@Seldaek ping

but whatever the result we would need to make sure that its easy to use this inside a template

Vincent Terraillon

I don't think this DOS problem should be handled by this bundle, it's the responsibility of the developper who is adding parameters, or it should be handled before the controller is called.

Miha Vrhovnik

It's ultra simple: base64_encode(hash_hmac('sha1',$concatGetParams,$apikey,true))

Jordi Boggiano

@LouTerrailloune The DDoS problem is that if you can specify any size on the fly, and if you cache the generated images, I can request every combination of X and Y until your disk is full, or your memory is full and you start deleting cached entries, and it makes everything slow. Call this paranoia if you will, but I think X and Y should be whitelisted.

Maybe it should be made optional though because as always, some people don't care about paranoid security measures. As for adding signing of GET params to our bundle, maybe. I'm not sure if this makes much sense. Generally using whitelists is much easier.. But if it's really needed please open an issue there. I don't really have time to look into it now.

Vincent Terraillon

@Seldaek : you missed my point. I understand the problem of possible DoS but what I'm saying is that in this bundle we don't need to handle this because we have no variable parameter in our routes. The problem will appear if someone is extending the bundle to add parameters. I think this person should take care of the DoS problem, not this bundle.

Marc Weistroff
marcw commented May 28, 2012

:+1: on what @LouTerrailloune is saying. DDoS protection should not be part of this bundle. The proposed feature is a killer one, imho.

Lukas Kahwe Smith
Owner

well there else should the DDos protection be? at any rate .. i have been and will be very busy the coming weeks, so can someone summaries the current discussion, pros and cons? also this PR needs to be rebased.

Lukas Kahwe Smith
Owner

@sixty-nine can you have a look at this PR too?

Dan

I already checked this but it seems a bit more delicate, and I don't have an opinion.
I am very busy this week but will try to summarize the comments as soon as possible.

Vincent Terraillon
  1. Many of us will agree that limiting to 'width' and 'height' is not a good solution (this PR is also limited to the 'thumbnail' filter).
  2. We have everything in the bundle to achieve it 'by hand' (see @mheleniak solution above)

What about this solution to allow the designer to set width/height of the generated picture ?

<img src="{{ '/640x480/relative/path/to/image.jpg' | imagine_filter('my_thumb') }}" />

To handle it, you write a custom controller that extends the one in the bundle:

public function filterAction(Request $request, $path, $filter)
{
    // extract width/height form path, and then remove it
    // I think we can keep it to store all versions and avoid caching problems if designer change size
    $pathParts = explode('/', $path);
    list($width, $height) = explode('x', $pathParts[0]);
    $path = implode('/', array_slice($pathParts, 1));

    $filterConfig = $this->filterManager->getFilterConfiguration();
    $config = $filterConfig->get($filter);
    $config['filters']['thumbnail']['size'] = array($width, $height);
    // patch your other filter config here !
    $filterConfig->set($filter, $config);

    return parent::filterAction($request, $path, $filter);
}

Error checking should be added of course.

Anton Babenko

Closing in favour of #311, #312, #313

Anton Babenko antonbabenko closed this February 03, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
16  Controller/ImagineController.php
@@ -4,13 +4,20 @@
4 4
 
5 5
 use Symfony\Component\HttpFoundation\Request;
6 6
 use Symfony\Component\HttpFoundation\Response;
  7
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
7 8
 use Liip\ImagineBundle\Imagine\Cache\CacheManager;
8 9
 use Liip\ImagineBundle\Imagine\Data\DataManager;
9 10
 use Liip\ImagineBundle\Imagine\Filter\FilterManager;
  11
+use Liip\ImagineBundle\Imagine\Filter\FilterConfiguration;
10 12
 
11 13
 class ImagineController
12 14
 {
13 15
     /**
  16
+     * @var FilterConfiguration
  17
+     */
  18
+    protected $filterConfiguration;
  19
+
  20
+    /**
14 21
      * @var DataManager
15 22
      */
16 23
     protected $dataManager;
@@ -32,8 +39,9 @@ class ImagineController
32 39
      * @param FilterManager $filterManager
33 40
      * @param CacheManager $cacheManager
34 41
      */
35  
-    public function __construct(DataManager $dataManager, FilterManager $filterManager, CacheManager $cacheManager)
  42
+    public function __construct(FilterConfiguration $filterConfiguration, DataManager $dataManager, FilterManager $filterManager, CacheManager $cacheManager)
36 43
     {
  44
+        $this->filterConfiguration = $filterConfiguration;
37 45
         $this->dataManager = $dataManager;
38 46
         $this->filterManager = $filterManager;
39 47
         $this->cacheManager = $cacheManager;
@@ -52,10 +60,16 @@ public function __construct(DataManager $dataManager, FilterManager $filterManag
52 60
      */
53 61
     public function filterAction(Request $request, $path, $filter)
54 62
     {
  63
+        $filterConfiguration = $this->filterConfiguration->updateFromRequest($filter, $request);
  64
+        
55 65
         $targetPath = $this->cacheManager->resolve($request, $path, $filter);
56 66
         if ($targetPath instanceof Response) {
57 67
             return $targetPath;
58 68
         }
  69
+        
  70
+        if (false === $this->filterConfiguration->isValidAccessKey($filter, $path, $request)) {
  71
+            throw new NotFoundHttpException('Incorrect hash');
  72
+        }
59 73
 
60 74
         $image = $this->dataManager->find($filter, $path);
61 75
         $response = $this->filterManager->get($request, $filter, $image, $path);
4  DependencyInjection/Configuration.php
@@ -48,6 +48,10 @@ public function getConfigTreeBuilder()
48 48
                             ->scalarNode('cache')->defaultNull()->end()
49 49
                             ->scalarNode('data_loader')->defaultNull()->end()
50 50
                             ->scalarNode('controller_action')->defaultNull()->end()
  51
+                            ->arrayNode('route')
  52
+                                ->useAttributeAsKey('name')
  53
+                                ->prototype('variable')->end()                                
  54
+                            ->end()
51 55
                             ->arrayNode('filters')
52 56
                                 ->useAttributeAsKey('name')
53 57
                                 ->prototype('array')
19  Imagine/Cache/CacheManager.php
@@ -106,7 +106,7 @@ private function getResolver($filter)
106 106
      * Gets filtered path for rendering in the browser
107 107
      *
108 108
      * @param string $path
109  
-     * @param string $filter
  109
+     * @param array|string $filter Filter name and parameters for the router
110 110
      * @param boolean $absolute
111 111
      *
112 112
      * @return string
@@ -115,10 +115,25 @@ public function getBrowserPath($targetPath, $filter, $absolute = false)
115 115
     {
116 116
         $params = array('path' => ltrim($targetPath, '/'));
117 117
 
  118
+        // Params passed from template may be array
  119
+        if (is_array($filter)) {
  120
+            $filterName = $filter[0];
  121
+
  122
+            $config = $this->filterConfig->get($filterName);
  123
+            if (!empty($config["route"]["hash"])) {
  124
+                $params["hash"] = substr(md5($filter[1] . "|" . $filter[2] . "|" . $targetPath), 0, 4);
  125
+            }
  126
+
  127
+            $params['width'] = $filter[1];
  128
+            $params['height'] = $filter[2];
  129
+        } else {
  130
+            $filterName = $filter;
  131
+        }
  132
+
118 133
         return str_replace(
119 134
             urlencode($params['path']),
120 135
             urldecode($params['path']),
121  
-            $this->router->generate('_imagine_'.$filter, $params, $absolute)
  136
+            $this->router->generate('_imagine_'.$filterName, $params, $absolute)
122 137
         );
123 138
     }
124 139
 
50  Imagine/Filter/FilterConfiguration.php
@@ -2,6 +2,8 @@
2 2
 
3 3
 namespace Liip\ImagineBundle\Imagine\Filter;
4 4
 
  5
+use Symfony\Component\HttpFoundation\Request;
  6
+
5 7
 class FilterConfiguration
6 8
 {
7 9
     /**
@@ -41,4 +43,52 @@ public function set($filter, array $config)
41 43
     {
42 44
         return $this->filters[$filter] = $config;
43 45
     }
  46
+
  47
+    /**
  48
+     * Update filter configuration with values from Request object
  49
+     * 
  50
+     * @param string $filter
  51
+     * @param Request $request
  52
+     *
  53
+     * @return array
  54
+     */
  55
+    public function updateFromRequest($filter, Request $request)
  56
+    {
  57
+        $filterConfiguration = $this->get($filter);
  58
+
  59
+        if (!empty($filterConfiguration['route'])) {
  60
+            array_walk_recursive($filterConfiguration['filters'], function(&$item, $key) use ($request) {
  61
+                    if ($item !== ($lookupItem = str_replace('$', '', $item)) && $request->get($lookupItem)) {
  62
+                        $item = $request->get($lookupItem);
  63
+                    }
  64
+                });
  65
+
  66
+            $filterConfiguration = $this->set($filter, $filterConfiguration);
  67
+        }
  68
+
  69
+        return $filterConfiguration;
  70
+    }
  71
+
  72
+    /**
  73
+     * Verify if provided access key (hash) is valid?
  74
+     * 
  75
+     * @param string $filter
  76
+     * @param string $path
  77
+     * @param Request $request
  78
+     *
  79
+     * @return boolean
  80
+     */
  81
+    public function isValidAccessKey($filter, $path, Request $request)
  82
+    {
  83
+
  84
+        $filterConfiguration = $this->get($filter);
  85
+
  86
+        if (!isset($filterConfiguration["route"]["hash"]) || false === $filterConfiguration["route"]["hash"]) {
  87
+            return true;
  88
+        }
  89
+
  90
+        $validHash = substr(md5($request->get('width') . "|" . $request->get('height') . "|" . $path), 0, 4);
  91
+
  92
+        return $request->get('hash') == $validHash;
  93
+    }
44 94
 }
43  README.md
Source Rendered
@@ -148,6 +148,19 @@ Or if you're using PHP templates:
148 148
 <img src="<?php $this['imagine']->filter('/relative/path/to/image.jpg', 'my_thumb', true) ?>" />
149 149
 ```
150 150
 
  151
+It is also possible to specify width and height in template. Refer to *Routing* section for more information about required configuration.
  152
+
  153
+``` jinja
  154
+<img src="{{ '/relative/path/to/image.jpg' | imagine_filter(['my_thumb', 200, 300]) }}" />
  155
+```
  156
+
  157
+Or if you are using PHP templates:
  158
+
  159
+``` php
  160
+<img src="<?php $this['imagine']->filter('/relative/path/to/image.jpg', array('my_thumb', 200, 300)) ?>" />
  161
+```
  162
+
  163
+
151 164
 Note: Using the ``dev`` environment you might find that the images are not properly rendered when
152 165
 using the template helper. This is likely caused by having ``intercept_redirect`` enabled in your
153 166
 application configuration. To ensure that the images are rendered disable this option:
@@ -219,6 +232,7 @@ Each filter set that you specify has the following options:
219 232
  - `data_loader` - override the default data loader
220 233
  - `controller_action` - override the default controller action
221 234
  - `format` - hardcodes the output format (aka the requested format is ignored)
  235
+ - `route` - optional array with `pattern` and `requirements` key. Used to pass variables like width/height in URI. Refer to *Routing* section for more information.
222 236
 
223 237
 ## Built-in Filters
224 238
 
@@ -393,3 +407,32 @@ With a custom data loader it is possible to dynamically modify the configuration
393 407
 be applied to the image. To do this simple store the filter configuration along with the
394 408
 image. Inside the data loader read this configuration and dynamically change the configuration
395 409
 for the given filter inside the ``FilterConfiguration`` instance.
  410
+
  411
+## Routing
  412
+
  413
+By specifying route `pattern` and `requirements` it is possible to pass parameters from URI.
  414
+This is useful for passing image sizes dynamically and use them inside ``FilterConfiguration`` instance (refer to *Dynamic filters* for more information).
  415
+
  416
+Configuration looks like this:
  417
+
  418
+``` yaml
  419
+liip_imagine:
  420
+    filter_sets:
  421
+        my_thumb:
  422
+            route:
  423
+              hash: true  # true or false
  424
+              pattern: /{width}x{height}
  425
+              requirements: { width: '[\d]{1,4}', height: '[\d]{1,4}' }
  426
+        filters:
  427
+          thumbnail: { size: [$width, $height], mode: inset }
  428
+```
  429
+
  430
+Route variables `width` and `height` are populated in filters configuration.
  431
+
  432
+Note: When `hash` is set to false, then it allows everyone to generate images of any size (which is potential security breach).
  433
+Make sure that you have `hash` set to true, when using routes. Be very careful with this option and always enable it on production environment!
  434
+
  435
+`hash` parameter is checked only when image of specified size has not been created yet.
  436
+When image has been cached then `hash` is not verified (means that everybody can access cached image, as usually).
  437
+
  438
+Valid image URL looks like: `http://localhost/cache/my_thumb/140x250/image.jpg?hash=eab3`
1  Resources/config/imagine.xml
@@ -74,6 +74,7 @@
74 74
         <!-- Controller -->
75 75
 
76 76
         <service id="liip_imagine.controller" class="%liip_imagine.controller.class%">
  77
+            <argument type="service" id="liip_imagine.filter.configuration" />
77 78
             <argument type="service" id="liip_imagine.data.manager" />
78 79
             <argument type="service" id="liip_imagine.filter.manager" />
79 80
             <argument type="service" id="liip_imagine.cache.manager" />
8  Routing/ImagineLoader.php
@@ -40,11 +40,19 @@ public function load($resource, $type = null)
40 40
                 } elseif ('' !== $filter) {
41 41
                     $pattern .= '/'.$filter;
42 42
                 }
  43
+                
  44
+                if (!empty($config['route']['pattern'])) {
  45
+                    $pattern .= $config['route']['pattern'];
  46
+                }
43 47
 
44 48
                 $defaults = array(
45 49
                     '_controller' => empty($config['controller_action']) ? $this->controllerAction : $config['controller_action'],
46 50
                     'filter' => $filter,
47 51
                 );
  52
+                
  53
+                if (!empty($config['route']['requirements'])) {
  54
+                    $requirements = array_merge($requirements, $config['route']['requirements']);
  55
+                }
48 56
 
49 57
                 $routes->add('_imagine_'.$filter, new Route(
50 58
                     $pattern.'/{path}',
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.