Redimensionamento de imagens em tempo real

Praticamente, em qualquer aplicação web que usa imagens, existe a necessidade de gerar versões menores dessas imagens, e muitas vezes, em vários formatos adicionais.
Além disso, adicionar novos tamanhos a uma aplicação existente pode ser um pouco desafiador. Portanto, a tarefa é:

Tarefa

Vamos delinear a lista de requisitos:

  • Gerar imagens adicionais em qualquer formato em tempo real, sem necessidade de implementar funcionalidade adicional na aplicação a qualquer momento durante sua existência;
  • Imagens adicionais não devem ser geradas a cada requisição;
  • Fechar a possibilidade de gerar imagens adicionais em formatos não estabelecidos.

Vou explicar o último ponto, pois ele é um pouco contraditório ao primeiro. Se tornarmos a geração de quaisquer imagens aberta, existe a possibilidade de um ataque ao site através da geração de um grande número de requisições para redimensionamento de imagem em um número infinito de formatos, portanto, essa vulnerabilidade precisa ser fechada.

Configuração da instalação do nginx

Para atender aos requisitos acima mencionados, precisaremos do seguinte conjunto de módulos do nginx:

Módulos ngx_http_image_filter_module e ngx_http_secure_link_module não estão instalados por padrão, portanto, precisam ser especificados na fase de configuração da instalação nginx:

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

Configuração do nginx

Na configuração do nosso host, adicionamos um novo localização e parâmetros gerais de 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;
        }
...
    }
...

Também adicionamos um novo host na configuração:

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

No final, as imagens adicionais podem ser acessadas através dos links:

* try_files — sensível a espaços e caracteres russos, por isso foi necessário implementar uma solução alternativa com alias.

Uso em aplicativo web

No nível do aplicativo web, pode-se fazer o seguinte procedimento (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'
                );

Embora eu também recomendaria calcular os tamanhos preview.

Truques

Ao remover a imagem original, a pré-visualização, naturalmente, não será removida do cache até que o cache seja invalidado, e no nosso caso, as pré-visualizações podem existir por até um dia após a remoção, mas esse é o máximo em termos de tempo.

original

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster