I næsten enhver webapplikation, der bruger billeder, er der et behov for at generere miniaturekopier af disse billeder, ofte i flere forskellige formater.
Det medfører også en del hovedpine at tilføje nye størrelser til en eksisterende applikation. Her er opgaven:
Regler for godkendelse af merge-requests
Lad os definere kravlisten:
- Generere ekstra billeder i alle formater on-the-fly uden at kræve yderligere funktionalitet i applikationen på noget tidspunkt i applikationens livscyklus;
- Ekstra billeder må ikke genereres ved hver anmodning;
- Luk muligheden for at generere ekstra billeder i ikke-definerede formater.
Jeg vil forklare det sidste punkt, da det strider lidt imod det første punkt. Hvis vi åbner op for generering af alle billeder, er der en mulighed for angreb på websitet ved at sende et stort antal anmodninger om at ændre størrelsen på billeder i uendeligt mange formater, så denne sårbarhed skal lukkes.
Nginx installationskonfiguration
For at opfylde ovenstående krav, har vi brug for følgende sæt af nginx-moduler:
- — til re-sizing af billeder;
- — til caching;
- — til beskyttelse mod spam;
Moduler ngx_http_image_filter_module og ngx_http_secure_link_module de installeres som standard ikke, så de skal angives under konfigurationstrinnet nginx:
phoinix@phoinix-work:~/src/nginx-0.8.29
$ ./configure --with-http_secure_link_module --with-http_image_filter_module
Nginx konfiguration
Vi tilføjer en ny i konfigurationen af vores vært location og de generelle cache-parametre:
...
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;
}
...
}
...
Vi tilføjer også en ny vært i konfigurationen:
server {
server_name minprojekt.dk;
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; }
}
Som et resultat kan ekstra billeder hentes via links:
- [md5]/[path_to_image]
- [md5]/[size]/[path_to_image]
- [md5]/[size]/[path_to_image]
* try_files — følsom over for mellemrum og russiske symboler, så vi måtte lave en workaround med alias.
Brug i webapplikationen
På webapplikationsniveau kan følgende procedure udføres (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'
);
Selvom jeg også vil anbefale at beregne størrelser preview.
Rive
Når det oprindelige billede slettes, vil preview naturligvis ikke blive fjernet fra cachen, før cachen inddrages, og i vores tilfælde kan previews eksistere i op til 24 timer efter sletning, men det er maksimumstiden.
Kilde: habr.com
