Resizing Images on the Fly

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:

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:

* 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.

originalen

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster