Ridimensionamento delle immagini al volo

Praticamente in qualsiasi applicazione web che utilizza immagini esiste la necessità di creare versioni ridotte di queste immagini, spesso in diversi formati aggiuntivi.
Inoltre, aggiungere nuove dimensioni a un'applicazione esistente crea qualche disagio. Da qui la questione:

Compito

Definiamo un elenco di requisiti:

  • Creare immagini aggiuntive di qualsiasi formato al volo senza dover aggiungere funzionalità extra all'applicazione in qualsiasi momento della sua esistenza;
  • Le immagini aggiuntive non devono essere generate ad ogni richiesta;
  • Chiudere la possibilità di generare immagini aggiuntive in formati non specificati.

Spiegherò l'ultimo punto, poiché è leggermente contrario al primo punto. Se rendiamo aperta la generazione di qualsiasi immagine, c'è il rischio di attacchi al sito attraverso la creazione di un numero enorme di richieste per il ridimensionamento dell'immagine in un numero infinito di formati, quindi questa vulnerabilità deve essere chiusa.

Configurazione dell'installazione di nginx

Per soddisfare i requisiti sopra elencati, avremo bisogno dei seguenti moduli nginx:

Moduli ngx_http_image_filter_module e ngx_http_secure_link_module di default non sono installati, 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 al nostro host la nuova location e i parametri generali della cache:

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

Aggiungiamo anche un nuovo host nella configurazione:

server {
    server_name                     myproject.ru;
    listen                          81;

    access_log /www/myproject.it/logs/nginx.preview.access_log;
    error_log /www/myproject.it/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.it/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.it/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.it/images/$3;
        try_files "" @404;

        if ($secure_link = "") { return 404; }

        image_filter resize $width $height;
    }

    location @404 { return 404; }
}

In definitiva, le immagini aggiuntive possono essere recuperate tramite i link:

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

Utilizzo nell'applicazione web

A livello di applicazione web, è possibile effettuare 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 raccomanderei di calcolare le dimensioni anteprima.

Grattacapo

Quando l'immagine originale viene rimossa, le anteprime, naturalmente, non verranno eliminate dalla cache fino a quando la cache non viene invalidata, e nel nostro caso le anteprime possono esistere fino a un giorno dopo la rimozione, ma questo è il massimo tempo.

originale

Fonte: habr.com

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