Em quase todas as aplicações web que utilizam imagens, é necessário criar pequenas cópias dessas imagens e, muitas vezes, existem vários formatos para imagens adicionais.
Adicionar novas dimensões a um aplicativo existente também causa algumas dores de cabeça. Daí a tarefa:
Tarefa
Vamos denotar a lista de requisitos:
- Gerar imagens adicionais de qualquer formato dinamicamente sem introduzir funcionalidades adicionais no aplicativo a qualquer momento durante a existência do aplicativo;
- Imagens adicionais não precisam ser geradas em todas as solicitações;
- Desative a capacidade de gerar imagens adicionais de formatos não especificados.
Explicarei o último ponto, porque contradiz ligeiramente o primeiro ponto. Se abrirmos a geração de alguma imagem, existe a possibilidade de um ataque ao site gerando um grande número de solicitações de redimensionamento da imagem em um número infinito de formatos, portanto esta vulnerabilidade precisa ser fechada.
configuração de instalação do nginx
Para resolver os requisitos acima, precisamos do seguinte conjunto de módulos nginx:
- — para redimensionar imagens;
- - para armazenamento em cache;
- — para proteção contra spam;
Módulos ngx_http_image_filter_module и ngx_http_secure_link_module não são instalados por padrão, portanto devem ser especificados no estágio 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 nginx
Adicionamos um novo à nossa configuração de host local 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 à 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;
# Especifique a palavra secreta para md5
segredo_do_link_seguro;
# Os erros são enviados para um local separado
página_de_erro 403 404 415 500 502 503 504 = @404;
# localização Para filtro de tamanho
localização ~ ^/i/[^/]+/(.+) {
# hack sujo de Igor Sysoev *
apelido /www/myproject.ru/images/$1;
try_files "" @404;
# Verifique a exatidão do link e do md5
se ($secure_link = "") { retornar 404; }
# Use o filtro apropriado
tamanho do filtro de imagem;
}
# Por analogia, o restante dos locais para outros filtros
localização ~ ^/c/[^/]+/(d+|-)x(d+|-)/(.+) {
definir $largura $1;
definir $altura $2;
apelido /www/myproject.ru/images/$3;
try_files "" @404;
se ($secure_link = "") { retornar 404; }
filtro_de_imagem recorte $largura $altura;
}
localização ~ ^/r/[^/]+/(d+|-)x(d+|-)/(.+) {
definir $largura $1;
definir $altura $2;
apelido /www/myproject.ru/images/$3;
try_files "" @404;
se ($secure_link = "") { retornar 404; }
filtro_de_imagem redimensionar $largura $altura;
}
localização @404 { retornar 404; }
}
Como resultado, imagens adicionais podem ser obtidas através dos seguintes links:
- [md5]/[caminho_para_imagem]
- [md5]/[tamanho]/[caminho_para_imagem]
- [md5]/[tamanho]/[caminho_para_imagem]
* try_files - sensível a espaços e caracteres russos, então tive que fazer uma muleta com aliás.
Use em um aplicativo da web
No nível da aplicação web, você pode 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;
}
meu $preview_path = &proxy_image(
fonte => 'image1.jpg',
altura => 100,
largura => 100,
filtro => 'redimensionar'
);
Embora eu também recomende calcular os tamanhos visualização.
Ancinho
Ao excluir a imagem original, as visualizações, naturalmente, não serão excluídas do cache até que o cache seja invalidado e, no nosso caso, as visualizações podem existir por um dia após a exclusão, mas este é o tempo máximo.
Fonte: habr.com
