Practically any web application using images has the need to create resized copies of these images, and often there are several formats for additional images.
Adding new sizes to an existing application can also be quite challenging. Hence the task:
Առաջադրանք
Let's outline the list of requirements:
- To generate additional images of any formats on the fly without adding extra functionality to the application at any moment during its existence;
- Additional images must not be generated with every request;
- Restrict the ability to generate additional images in unregistered formats.
I'll explain the last point, as it slightly contradicts the first point. If we allow the generation of any images, there exists a risk of attacks on the site by generating a large number of resize requests for an infinite number of formats, so this vulnerability needs to be addressed.
Nginx installation configuration
To meet the above requirements, we will need the following set of nginx modules:
- — for image resizing;
- — for caching;
- — for spam protection;
Modules ngx_http_image_filter_module և ngx_http_secure_link_module are not installed by default, so they need to be specified during the installation configuration step nginx:
phoinix@phoinix-work:~\/src\/nginx-0.8.29
$ .\/configure --with-http_secure_link_module --with-http_image_filter_module
Nginx configuration
We add a new entry to our host configuration 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 {
սերվերի_անուն myproject.ru;
լսել 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 retrieved via links:
- [md5]/[path_to_image]
- [md5]/[size]/[path_to_image]
- [md5]/[size]/[path_to_image]
* try_files — sensitive to spaces and Cyrillic characters, hence we had to implement a workaround with alias.
Using in a web application
At the web application level, you can implement 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 also recommend calculating the sizes preview.
Hiccups
Առաջին օրինակի հեռացման դեպքում, փոքրամասնության ակնարկները, բնականաբար, չեն հեռացվի դիրքերում, այնքան ժամանակ, քանի դեռ դիսկոդը ինվալիդացված չէ, իսկ մեր դեպքում ակնարկները կարող են գոյություն ունենալ մեկ օր հետո հեռացվելուց, սակայն դա այնքան ժամանակահատվածի առավելագույնն է:
Ընտանիք: habr.com
