Dalam hampir mana-mana aplikasi web yang menggunakan imej, terdapat keperluan untuk mencipta salinan kecil imej ini, dan selalunya terdapat beberapa format untuk imej tambahan.
Menambah dimensi baharu pada aplikasi sedia ada juga menyebabkan beberapa pening kepala. Oleh itu tugas:
Petugas
Mari kita nyatakan senarai keperluan:
- Hasilkan imej tambahan bagi sebarang format dengan segera tanpa memperkenalkan fungsi tambahan ke dalam aplikasi pada bila-bila masa semasa kewujudan aplikasi;
- Imej tambahan tidak perlu dihasilkan pada setiap permintaan;
- Lumpuhkan keupayaan untuk menjana imej tambahan daripada format yang tidak ditentukan.
Saya akan menerangkan perkara terakhir, kerana ia sedikit bercanggah dengan perkara pertama. Jika kita membuat penjanaan mana-mana imej terbuka, maka terdapat kemungkinan serangan ke atas tapak dengan menjana sejumlah besar permintaan untuk mengubah saiz imej kepada bilangan format yang tidak terhingga, jadi kelemahan ini perlu ditutup.
konfigurasi pemasangan nginx
Untuk menyelesaikan keperluan di atas, kami memerlukan set modul nginx berikut:
ngx_http_image_filter_module β untuk mengubah saiz imej;ngx_http_proxy_module - untuk caching;ngx_http_secure_link_module β untuk melindungi daripada spam;
Modul ngx_http_image_filter_module ΠΈ ngx_http_secure_link_module tidak dipasang secara lalai, jadi ia mesti dinyatakan pada peringkat konfigurasi pemasangan nginx:
phoinix@phoinix-work:~/src/nginx-0.8.29
$ ./configure --with-http_secure_link_module --with-http_image_filter_module
konfigurasi nginx
Kami menambah yang baharu pada konfigurasi hos kami lokasi dan parameter cache umum:
...
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;
}
...
}
...
Kami juga menambah hos baharu pada konfigurasi:
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; }
}
Hasilnya, imej tambahan boleh diperoleh menggunakan pautan berikut:
myproject.ru/preview/i [md5]/[path_to_image]myproject.ru/preview/c [md5]/[saiz]/[path_to_image]myproject.ru/preview/r [md5]/[saiz]/[path_to_image]
* try_files β sensitif kepada ruang dan aksara Rusia, jadi saya terpaksa membuat tongkat dengan alias.
Gunakan dalam aplikasi web
Di peringkat aplikasi web, anda boleh melakukan prosedur berikut (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'
);
Walaupun saya juga akan mengesyorkan mengira saiz preview.
Rake
Apabila memadamkan imej asal, pratonton, secara semula jadi, tidak akan dipadamkan daripada cache sehingga cache tidak sah, dan dalam kes kami, pratonton boleh wujud selama sehari selepas pemadaman, tetapi ini adalah masa maksimum.
Sumber: www.habr.com