In fast jeder Webanwendung, die Bilder verwendet, besteht die Notwendigkeit, kleinere Versionen dieser Bilder zu erstellen, wobei oft mehrere zusätzliche Bildformate erforderlich sind.
Ebenfalls etwas problematisch ist das Hinzufügen neuer Größen zu einer bestehenden Anwendung. Daraus ergibt sich die Aufgabe:
Ziel
Lassen Sie uns eine Liste der Anforderungen festlegen:
- Zusätzliche Bilder in beliebigen Formaten sollen dynamisch erstellt werden können, ohne dass während der gesamten Lebensdauer der Anwendung zusätzliche Funktionen in die Anwendung integriert werden müssen;
- Zusätzliche Bilder dürfen nicht bei jeder Anfrage erstellt werden;
- Die Möglichkeit zur Erstellung zusätzlicher Bilder in nicht festgelegten Formaten muss geschlossen werden.
Ich erkläre den letzten Punkt, da er dem ersten Punkt etwas widerspricht. Wenn wir die Erstellung beliebiger Bilder öffnen, besteht die Möglichkeit, die Website anzugreifen, indem eine große Menge an Anfragen zur Größenänderung von Bildern in unendlich vielen Formaten erstellt wird, weshalb diese Sicherheitsanfälligkeit geschlossen werden muss.
Nginx-Installationskonfiguration
Um die oben genannten Anforderungen zu erfüllen, benötigen wir das folgende Set an nginx-Modulen:
- — für die Größenänderung von Bildern;
- — für das Caching;
- — zum Schutz vor Spam;
Module ngx_http_image_filter_module und ngx_http_secure_link_module sind standardmäßig nicht enthalten, daher müssen sie während der Konfiguration angegeben werden. nginx:
phoinix@phoinix-work:~/src/nginx-0.8.29
$ ./configure --with-http_secure_link_module --with-http_image_filter_module
nginx-Konfiguration
Fügen Sie in die Konfiguration unseres Hosts einen neuen location und allgemeine Cache-Einstellungen hinzu:
...
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;
}
...
}
...
Fügen Sie auch einen neuen Host zur Konfiguration hinzu:
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; }
}
Die zusätzlichen Bilder können schließlich über die Links abgerufen werden:
- [md5]/[path_to_image]
- [md5]/[size]/[path_to_image]
- [md5]/[size]/[path_to_image]
* try_files — ist empfindlich gegenüber Leerzeichen und russischen Zeichen, daher musste ein Workaround geschaffen werden alias.
Verwendung in der Webanwendung
Auf der Ebene der Webanwendung kann folgendes Verfahren (Perl) durchgeführt werden:
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'
);
Obwohl ich empfehlen würde, die Größen zu berechnen Vorschau.
Rätsel
Wenn das Originalbild gelöscht wird, werden die Vorschaubilder selbstverständlich nicht aus dem Cache gelöscht, bis der Cache invalidiert wird. In unserem Fall können Previews bis zu einem Tag nach der Löschung existieren, aber das ist das Maximum.
Quelle: habr.com
