ืฉื ื” ืืช ื’ื•ื“ืœ ื”ืชืžื•ื ื•ืช ืชื•ืš ื›ื“ื™ ืชื ื•ืขื”

ื›ืžืขื˜ ื‘ื›ืœ ืืคืœื™ืงืฆื™ื™ืช ืื™ื ื˜ืจื ื˜ ื”ืžืฉืชืžืฉืช ื‘ืชืžื•ื ื•ืช, ื™ืฉ ืฆื•ืจืš ืœื™ืฆื•ืจ ืขื•ืชืงื™ื ืงื˜ื ื™ื ืฉืœ ืชืžื•ื ื•ืช ืืœื•, ื•ืœืขื™ืชื™ื ืงืจื•ื‘ื•ืช ื™ืฉื ื ืžืกืคืจ ืคื•ืจืžื˜ื™ื ืœืชืžื•ื ื•ืช ื ื•ืกืคื•ืช.
ื”ื•ืกืคืช ืžื™ืžื“ื™ื ื—ื“ืฉื™ื ืœืืคืœื™ืงืฆื™ื” ืงื™ื™ืžืช ื’ื ื’ื•ืจืžืช ืœื›ืžื” ื›ืื‘ื™ ืจืืฉ. ืžื›ืืŸ ื”ืžืฉื™ืžื”:

ืžืฉื™ืžื”

ื ืกืžืŸ ืืช ืจืฉื™ืžืช ื”ื“ืจื™ืฉื•ืช:

  • ืฆื•ืจ ืชืžื•ื ื•ืช ื ื•ืกืคื•ืช ืžื›ืœ ืคื•ืจืžื˜ ืชื•ืš ื›ื“ื™ ืชื ื•ืขื” ืžื‘ืœื™ ืœื”ื›ื ื™ืก ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ื ื•ืกืคืช ืœื™ื™ืฉื•ื ื‘ื›ืœ ืขืช ื‘ืžื”ืœืš ืงื™ื•ืžื” ืฉืœ ื”ื™ื™ืฉื•ื;
  • ืื™ืŸ ืฆื•ืจืš ืœื™ืฆื•ืจ ืชืžื•ื ื•ืช ื ื•ืกืคื•ืช ื‘ื›ืœ ื‘ืงืฉื”;
  • ื”ืฉื‘ืช ืืช ื”ื™ื›ื•ืœืช ืœื™ืฆื•ืจ ืชืžื•ื ื•ืช ื ื•ืกืคื•ืช ื‘ืคื•ืจืžื˜ื™ื ืœื ืžื•ื’ื“ืจื™ื.

ืืกื‘ื™ืจ ืืช ื”ื ืงื•ื“ื” ื”ืื—ืจื•ื ื”, ื›ื™ ื”ื™ื ืกื•ืชืจืช ืžืขื˜ ืืช ื”ื ืงื•ื“ื” ื”ืจืืฉื•ื ื”. ืื ื ื’ืจื•ื ืœื™ืฆื™ืจืช ืชืžื•ื ื•ืช ื›ืœืฉื”ืŸ ืœืคืชื•ื—, ืื–ื™ ื™ืฉื ื” ืืคืฉืจื•ืช ืœื”ืชืงืคื” ืขืœ ื”ืืชืจ ืขืœ ื™ื“ื™ ื™ืฆื™ืจืช ืžืกืคืจ ืจื‘ ืฉืœ ื‘ืงืฉื•ืช ืœืฉื™ื ื•ื™ ื’ื•ื“ืœ ื”ืชืžื•ื ื” ืœืžืกืคืจ ืื™ื ืกื•ืคื™ ืฉืœ ืคื•ืจืžื˜ื™ื, ื•ืœื›ืŸ ื™ืฉ ืœืกื’ื•ืจ ืืช ื”ืคื’ื™ืขื•ืช ื”ื–ื•.

ืชืฆื•ืจืช ื”ืชืงื ืช nginx

ื›ื“ื™ ืœืคืชื•ืจ ืืช ื”ื“ืจื™ืฉื•ืช ืœืขื™ืœ, ืื ื• ื–ืงื•ืงื™ื ืœืกื˜ ื”ื‘ื ืฉืœ ืžื•ื“ื•ืœื™ nginx:

ืžื•ื“ื•ืœื™ื ngx_http_image_filter_module ะธ ngx_http_secure_link_module ืื™ื ื ืžื•ืชืงื ื™ื ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ื•ืœื›ืŸ ื™ืฉ ืœืฆื™ื™ืŸ ืื•ืชื ื‘ืฉืœื‘ ื”ื’ื“ืจืช ื”ื”ืชืงื ื” nginx:

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

ืชืฆื•ืจืช nginx

ืื ื• ืžื•ืกื™ืคื™ื ืื—ื“ ื—ื“ืฉ ืœืชืฆื•ืจืช ื”ืžืืจื— ืฉืœื ื• ืžื™ืงื•ื ื•ืคืจืžื˜ืจื™ื ื›ืœืœื™ื™ื ืฉืœ ืžื˜ืžื•ืŸ:

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

ืื ื• ื’ื ืžื•ืกื™ืคื™ื ืžืืจื— ื—ื“ืฉ ืœืชืฆื•ืจื”:

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

ื›ืชื•ืฆืื” ืžื›ืš, ื ื™ืชืŸ ืœืงื‘ืœ ืชืžื•ื ื•ืช ื ื•ืกืคื•ืช ื‘ืืžืฆืขื•ืช ื”ืงื™ืฉื•ืจื™ื ื”ื‘ืื™ื:

* try_files - ืจื’ื™ืฉ ืœืจื•ื•ื—ื™ื ื•ืœืชื•ื•ื™ื ืจื•ืกื™ื™ื, ืื– ื”ื™ื™ืชื™ ืฆืจื™ืš ืœืขืฉื•ืช ืื™ืชื• ืงื‘ ื›ื™ื ื•ื™.

ืฉื™ืžื•ืฉ ื‘ื™ื™ืฉื•ื ืื™ื ื˜ืจื ื˜

ื‘ืจืžืช ื™ื™ืฉื•ื ื”ืื™ื ื˜ืจื ื˜, ืืชื” ื™ื›ื•ืœ ืœื‘ืฆืข ืืช ื”ื”ืœื™ืš ื”ื‘ื (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'
                );

ืœืžืจื•ืช ืฉื”ื™ื™ืชื™ ืžืžืœื™ืฅ ื’ื ืœื—ืฉื‘ ืืช ื”ื’ื“ืœื™ื ืชืฆื•ื’ื” ืžืงื“ื™ืžื”.

Rake

ื‘ืขืช ืžื—ื™ืงืช ื”ืชืžื•ื ื” ื”ืžืงื•ืจื™ืช, ืชืฆื•ื’ื•ืช ืžืงื“ื™ืžื•ืช, ืžื˜ื‘ืข ื”ื“ื‘ืจื™ื, ืœื ื™ื™ืžื—ืงื• ืžื”ืžื˜ืžื•ืŸ ืขื“ ืœื‘ื™ื˜ื•ืœ ื”ืžื˜ืžื•ืŸ, ื•ื‘ืžืงืจื” ืฉืœื ื•, ืชืฆื•ื’ื•ืช ืžืงื“ื™ืžื•ืช ื™ื›ื•ืœื•ืช ืœื”ืชืงื™ื™ื ื™ื•ื ืœืื—ืจ ื”ืžื—ื™ืงื”, ืืš ื–ื”ื• ื”ื–ืžืŸ ื”ืžืงืกื™ืžืœื™.

ืžืงื•ืจื™

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”