Gyakorlatilag bármilyen webalkalmazásban, amely képeket használ, felmerül az igény, hogy csökkentett másolatokat készítsenek ezekből a képekből, és gyakran többféle formátumban.
Ezenkívül új méretek hozzáadása a meglévő alkalmazáshoz némi fejtörést okoz. Ezért a feladat a következő:
Feladat
Határozzuk meg a követelmények listáját:
- Képátméretezés bármilyen formátumban valós időben, anélkül, hogy bármilyen további funkciót kellene hozzáadni az alkalmazáshoz, bármikor az alkalmazás élettartama alatt;
- További képek ne készüljenek minden egyes kérésnél;
- Lehetővé tenni a nem meghatározott formátumú képek létrehozásának lezárását.
Elmagyarázom az utolsó pontot, mivel ez némileg ellentmond az elsőnek. Ha lehetővé tesszük bármilyen kép létrehozását, akkor lehetőség nyílik a weboldal támadására a kérés nagyszámú generálásával a képméretezéshez végtelen számú formátumban, ezért ezt a sebezhetőséget le kell zárni.
nginx telepítési konfiguráció
A fenti követelmények teljesítéséhez szükségünk lesz az alábbi nginx modulokra:
- — a képek átméretezésére;
- — a gyorsítótárazás érdekében;
- — a spam elleni védelem érdekében;
Modulok ngx_http_image_filter_module és ngx_http_secure_link_module alapértelmezés szerint nem telepítettek, ezért ezeket a telepítési konfiguráció során kell megadni nginx:
phoinix@phoinix-work:~\/src\/nginx-0.8.29
$ .\/configure --with-http_secure_link_module --with-http_image_filter_module
nginx konfiguráció
A host konfigurációjához új szakaszt adunk hozzá location és a gyorsítótárazás általános paraméterei:
...
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;
}
...
}
...
Továbbá új hostot adunk a konfigurációhoz:
server {
szerver_neve myproject.ru;
figyel 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 titok;
# Ошибки отправляем она отдельный 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; }
}
Ennek eredményeként a további képek elérhetők az alábbi linkeken:
- [md5]/[path_to_image]
- [md5]/[size]/[path_to_image]
- [md5]/[size]/[path_to_image]
* try_files — érzékeny a szóközökre és a cirill karakterekre, ezért workaround-ot kellett csinálni alias.
Használat webalkalmazásban
A webalkalmazás szintjén a következő eljárást lehet végrehajtani (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'
);
Bár azt is javasolnám, hogy számoljuk ki a méreteket preview.
Rács
Ha az eredeti képet töröljük, a préviews természetesen nem fognak eltűnni a gyorsítótárból, amíg a gyorsítótár nem érvénytelenül válik, és a mi esetünkben a préviews akár egy napig is létezhetnek a törlés után, de ez a maximális idő.
Forrás: habr.com
