Ridimensionamento delle immagini al volo

Praticamente in qualsiasi applicazione web che utilizza immagini c'è la necessità di generare miniature di queste immagini, e spesso ci sono diversi formati di immagini supplementari.
Aggiungere nuove dimensioni a un'applicazione esistente può essere piuttosto complicato. Da qui la necessità:

Compito

Definiamo un elenco di requisiti:

  • Generare immagini supplementari in qualsiasi formato al volo senza aggiungere funzionalità extra all'applicazione in qualsiasi momento della sua esistenza;
  • Le immagini supplementari non devono essere generate ad ogni richiesta;
  • Limitare la generazione di immagini supplementari a formati non stabiliti.

Spiegherò quest'ultimo punto, poiché è leggermente in contraddizione con il primo. Se rendiamo possibile la generazione di qualsiasi immagine, esiste la possibilità di attacco al sito da parte di un numero eccessivo di richieste per il ridimensionamento delle immagini in una quantità infinita di formati, pertanto questa vulnerabilità deve essere chiusa.

Configurazione dell'installazione di nginx

Per soddisfare i requisiti sopra citati avremo bisogno del seguente set di moduli nginx:

Moduli ngx_http_image_filter_module e ngx_http_secure_link_module per impostazione predefinita non sono inclusi, quindi devono essere specificati nella fase di configurazione dell'installazione nginx:

phoinix@phoinix-work:~/src/nginx-0.8.29
$ ./configure --with-http_secure_link_module --with-http_image_filter_module

Configurazione di nginx

Aggiungiamo nel file di configurazione del nostro host un nuovo location e parametri generali per la cache:

...
    proxy_cache_path /www/myprojects/cache livelli=1:2 chiave_zona=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;
        }
...
    }
...

Aggiungiamo anche un nuovo host nel configurazione:

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; }
}

Di conseguenza, le immagini supplementari possono essere recuperate tramite i seguenti link:

* try_files — sensibile agli spazi e ai caratteri russi, quindi è stato necessario implementare un workaround con alias.

Utilizzo nell'applicazione web

A livello dell'applicazione web, è possibile realizzare la seguente procedura (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'
                );

Anche se consiglio di considerare le dimensioni anteprima.

Rastrelli

Al momento della rimozione dell'immagine originale, i preview non verranno rimossi dalla cache finché la cache non viene invalidata, e nel nostro caso i preview possono esistere per un massimo di 24 ore dopo la rimozione, ma questo è il massimo temporale.

originale

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster