Ændr størrelsen på billeder i farten

I næsten enhver webapplikation, der bruger billeder, er der behov for at lave små kopier af disse billeder, og ofte er der flere formater til yderligere billeder.
Tilføjelse af nye dimensioner til en eksisterende applikation forårsager også nogle hovedpine. Derfor opgaven:

Opgave

Lad os betegne listen over krav:

  • Generer yderligere billeder af ethvert format på farten uden at introducere yderligere funktionalitet i applikationen på noget tidspunkt under applikationens eksistens;
  • Yderligere billeder behøver ikke at blive genereret på hver anmodning;
  • Deaktiver muligheden for at generere yderligere billeder i uspecificerede formater.

Jeg vil forklare det sidste punkt, fordi det er lidt i modstrid med det første punkt. Hvis vi gør genereringen af ​​billeder åben, så er der mulighed for et angreb på webstedet ved at generere et stort antal anmodninger om at ændre størrelsen på billedet til et uendeligt antal formater, så denne sårbarhed skal lukkes.

nginx installationskonfiguration

For at løse ovenstående krav har vi brug for følgende sæt nginx-moduler:

moduler ngx_http_image_filter_module и ngx_http_secure_link_module er ikke installeret som standard, så de skal angives på installationskonfigurationsstadiet 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 til vores værtskonfiguration placering og 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 til konfigurationen:

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

Som et resultat kan yderligere billeder fås ved at bruge følgende links:

* try_filer — følsom over for mellemrum og russiske tegn, så jeg var nødt til at lave en krykke med alias.

Brug i en webapplikation

På webapplikationsniveau kan du udføre følgende procedure (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ørrelserne forhåndsvisning.

Rive

Når du sletter det originale billede, vil forhåndsvisninger naturligvis ikke blive slettet fra cachen, før cachen er ugyldig, og i vores tilfælde kan forhåndsvisninger eksistere i en dag efter sletning, men dette er den maksimale tid.

оригинал

Kilde: www.habr.com

Tilføj en kommentar