Resizing slik v realnem času

V praktično vsakem spletnem programu, ki uporablja slike, obstaja potreba po ustvarjanju zmanjšanih kopij teh slik, pri čemer je včasih več dodatnih formatov slik.
Dodajanje novih dimenzij obstoječemu programu lahko povzroči nekaj glavobolov. Od tod naloga:

Naloga

Opredelimo seznam zahtev:

  • Ustvariti je treba dodatne slike vseh formatov v realnem času, brez vnašanja dodatne funkcionalnosti v program kadarkoli v času njegovega obstoja;
  • Dodatne slike se ne bi smele ustvarjati ob vsakem zahtevku;
  • Onemogočiti je treba možnost ustvarjanja dodatnih slik v neustreznih formatih.

Pojasnil bom zadnjo točko, saj je nekoliko v nasprotju s prvo. Če omogočimo ustvarjanje kakršnih koli slik, obstaja možnost napada na spletno mesto s pošiljanjem velikega števila zahtevkov za preoblikovanje slike v neskončno število formatov, zato je potrebno to ranljivost zapreti.

Konfiguracija namestitve nginx

Za izpolnitev zgoraj navedenih zahtev bomo potrebovali naslednji nabor nginx modulov:

Moduli ngx_http_image_filter_module in ngx_http_secure_link_module privzeto niso nameščeni, zato jih je treba navesti v fazi konfiguracije namestitve nginx:

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

Konfiguracija nginx

V konfiguracijo našega gostitelja dodajamo nov lokacija in skupne parametre predpomnjenja:

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

Prav tako dodamo nov gostitelj v konfiguracijo:

server {
    ime_strežnika                     myproject.ru;
    poslušaj                          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; }
}

Kot rezultat lahko dodatne slike dobimo preko povezav:

* try_files — občutljiv na presledke in ruske znake, zato je bilo treba narediti improvizacijo z alias.

Uporaba v spletnem aplikaciji

Na ravni spletne aplikacije lahko naredimo naslednjo proceduro (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'
                );

Čeprav bi še priporočil izračunati dimenzije preview.

Kljuke

Ob odstranitvi izvorne slike se preview seveda ne bodo odstranili iz predpomnilnika, dokler se predpomnilnik ne invalidira; v našem primeru lahko previews obstajajo do en dan po odstranitvi, a to je maksimum čas.

izvirnik

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster