Afbeeldingen on-the-fly resizen

Bijna elke webapplicatie die afbeeldingen gebruikt, heeft de behoefte om verkleinde versies van deze afbeeldingen te genereren, vaak in verschillende formaten.
Bovendien zorgt het toevoegen van nieuwe afmetingen aan een bestaande applicatie voor wat hoofdbrekens. Dit leidt tot de volgende taak:

Task

Laten we de lijst met vereisten opstellen:

  • Extra afbeeldingen van elk formaat on-the-fly genereren zonder extra functionaliteit aan de applicatie toe te voegen op elk moment tijdens de levensduur van de applicatie;
  • Extra afbeeldingen mogen niet bij elke aanvraag worden gegenereerd;
  • De mogelijkheid tot het genereren van extra afbeeldingen in niet-gestelde formaten sluiten.

Ik zal het laatste punt uitleggen, want het lijkt tegenstrijdig met het eerste punt. Als we het genereren van willekeurige afbeeldingen openstellen, bestaat de mogelijkheid van een aanval op de site door een groot aantal aanvragen voor het aanpassen van afbeeldingen in een oneindig aantal formaten, daarom moet deze kwetsbaarheid worden afgesloten.

Nginx installatie-configuratie

Om aan bovenstaande vereisten te voldoen, hebben we de volgende set Nginx-modules nodig:

Modules ngx_http_image_filter_module en ngx_http_secure_link_module worden standaard niet geïnstalleerd, daarom moeten ze tijdens de configuratie-installatie worden opgegeven met alles wat daarin al aanwezig is, en de inhoud van de map:

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

Nginx configuratie

We voegen een nieuwe host toe aan de configuratie van onze host locatie en de algemene cache-instellingen:

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

We voegen ook een nieuwe host toe aan de configuratie:

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

In totaal kunnen extra afbeeldingen worden opgehaald via de links:

* try_files — gevoelig voor spaties en Russische symbolen, dus we moesten een workaround maken met beheer van afbeeldingsaliassen.

Gebruik in webapplicatie

Op het niveau van de webapplicatie kan het volgende proces worden uitgevoerd (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'
                );

Hoewel ik ook zou aanbevelen om de afmetingen te berekenen preview.

Harken

Bij het verwijderen van de oorspronkelijke afbeelding zullen de previews natuurlijk niet uit de cache worden verwijderd totdat de cache ongeldig wordt gemaakt, en in ons geval kunnen de previews tot een dag na verwijdering bestaan, maar dat is het maximale tijdsbestek.

origineel

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster