Задача
Решение для динамического изменения размера изображений в веб-приложениях с соблюдением трёх основных требований:
- Формирование дополнительных изображений без модификации приложения.
- Кеширование превью для оптимизации.
- Ограничение доступных форматов для предотвращения DDoS-атак.
Конфигурация установки nginx
Требуются три модуля:
ngx_http_image_filter_module— для ресайза.ngx_http_proxy_module— для кеширования.ngx_http_secure_link_module— для защиты.
При компиляции nginx указываются флаги: --with-http_secure_link_module --with-http_image_filter_module.
Конфигурация nginx
Основной location на главном хосте с кешированием:
proxy_cache_path /www/myprojects/cache levels=1:2 keys_zone=image-preview:10m;
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";
proxy_cache_valid 200 1d;
proxy_cache_valid any 1m;
}
location = /preview/404 {
internal;
default_type image/gif;
alias /www/myprojects/image/noimage.gif;
} Отдельный хост на порту 81:
server {
server_name myproject.ru;
listen 81;
secure_link_secret secret;
error_page 403 404 415 500 502 503 504 = @404;
location ~ ^/i/[^/]+/(.+) {
alias /www/myproject.ru/images/$1;
try_files "" @404;
if ($secure_link = "") { return 404; }
image_filter size;
}
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; }
} URL-структура
http://myproject.ru/preview/i/[md5]/[path_to_image]— информация о размере.http://myproject.ru/preview/c/[md5]/[size]/[path_to_image]— обрезка.http://myproject.ru/preview/r/[md5]/[size]/[path_to_image]— изменение размера.
Использование в приложении (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;
} Грабли
При удалении исходного изображения, превью естественно удалятся из кеша не будут пока кеш не инвалидируется — они могут существовать до суток после удаления исходного файла.