📜 ⬆️ ⬇️

Resize images on the fly

Practically in any web application using images there is a need to form reduced copies of these images, and often, there are several formats of additional images.
It also causes some headaches to add new sizes to an existing application. Hence the task:

Task



Denote the list of requirements:


')
Let me explain the last point, because it slightly contradicts the first point. If we make the formation of any images open, then there is a possibility of an attack on the site by forming a large number of requests for resizing images in an infinite number of formats, so this vulnerability needs to be closed.

Nginx installation configuration



To solve the above requirements, we need the following set of nginx modules:



The ngx_http_image_filter_module and ngx_http_secure_link_module modules are not installed by default, so they must be specified during the nginx installation configuration stage:

phoinix@phoinix-work:~/src/nginx-0.8.29
$ ./configure --with-http_secure_link_module --with-http_image_filter_module


Nginx configuration



In the configuration of our host, we add a new location and general cache parameters:

...
proxy_cache_path /www/myprojects/cache levels=1:2 keys_zone=image-preview:10m;
...
server {
...
location ~ ^/preview/([cir])/(.+) {
#
set $oper $1;
#
set $remn $2;
#
proxy_pass http://myproject.ru:81/$oper/$remn;
proxy_intercept_errors on;
error_page 404 = /preview/404;
#
proxy_cache image-preview;
proxy_cache_key "$host$document_uri";
# 200 1
proxy_cache_valid 200 1d;
# 1
proxy_cache_valid any 1m;
}

#
location = /preview/404 {
internal;
default_type image/gif;
alias /www/myprojects/image/noimage.gif;
}
...
}
...


We also add a new host to the config:

server {
server_name myproject.ru;
listen 81;

access_log /www/myproject.ru/logs/nginx.preview.access_log;
error_log /www/myproject.ru/logs/nginx.preview.error_log info;

# md5
secure_link_secret secret;

# location
error_page 403 404 415 500 502 503 504 = @404;

# location size
location ~ ^/i/[^/]+/(.+) {

# *
alias /www/myproject.ru/images/$1;
try_files "" @404;

# md5
if ($secure_link = "") { return 404; }

#
image_filter size;
}

# location
location ~ ^/c/[^/]+/(\d+|-)x(\d+|-)/(.+) {
set $width $1;
set $height $2;

alias /www/myproject.ru/images/$3;
try_files "" @404;

if ($secure_link = "") { return 404; }

image_filter crop $width $height;
}

location ~ ^/r/[^/]+/(\d+|-)x(\d+|-)/(.+) {
set $width $1;
set $height $2;

alias /www/myproject.ru/images/$3;
try_files "" @404;

if ($secure_link = "") { return 404; }

image_filter resize $width $height;
}

location @404 { return 404; }
}


As a result, additional images can be taken on the links:



* try_files is sensitive to spaces and Russian characters, so I had to make a crutch with alias .

Use in web application



At the web application level, you can do the following procedure (Perl):

sub proxy_image {
use Digest::MD5 qw /md5_hex/;
my %params = @_;
my $filter = {
size => 'i',
resize => 'r',
crop => 'c'
}->{$params{filter}} || 'r';
my $path = ($filter ne 'i' ?
( $params{height} || '_' ) . 'x' . ( $params{width} || '_' ) . '/' :
()
) . $params{source};
my $md5 = md5_hex( $path . 'secret' );
$path = '/preview/' . $filter . '/' . $md5 . '/' . $path;
return $path;
}

my $preview_path = &proxy_image(
source => 'image1.jpg',
height => 100,
width => 100,
filter => 'resize'
);


Although I would recommend recommending preview sizes.

Rake



When deleting the original image, the preview, of course, will not be removed from the cache until the cache is not disabled, and in our case, the preview may exist within a day after deletion, but this is the maximum time.

original

Source: https://habr.com/ru/post/77873/


All Articles