เบ›เบฑเบšเบ‚เบฐเปœเบฒเบ”เบฎเบนเบšเบžเบฒเบšเป„เบ”เป‰เบ—เบฑเบ™เบ—เบต

เปƒเบ™เป€เบเบทเบญเบšเบ—เบธเบเบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเป€เบงเบฑเบšเป„เบŠเบ•เปŒเบ—เบตเปˆเปƒเบŠเป‰เบฎเบนเบšเบžเบฒเบš, เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบชเป‰เบฒเบ‡เบชเปเบฒเป€เบ™เบปเบฒเบ‚เบฐเบซเบ™เบฒเบ”เบ™เป‰เบญเบเบ‚เบญเบ‡เบฎเบนเบšเบžเบฒเบšเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰, เปเบฅเบฐเบกเบฑเบเบˆเบฐเบกเบตเบซเบผเบฒเบเบฎเบนเบšเปเบšเบšเบชเปเบฒเบฅเบฑเบšเบฎเบนเบšเบžเบฒเบšเป€เบžเบตเปˆเบกเป€เบ•เบตเบก.
เบเบฒเบ™เป€เบžเบตเปˆเบกเบ‚เบฐเปœเบฒเบ”เปƒเปเปˆเปƒเบซเป‰เบเบฑเบšเปเบญเบฑเบšเบžเบฅเบดเป€เบ„เบŠเบฑเบ™เบ—เบตเปˆเบกเบตเบขเบนเปˆเปเบฅเป‰เบงเบเบฑเบ‡เป€เบฎเบฑเบ”เปƒเบซเป‰เป€เบเบตเบ”เบญเบฒเบเบฒเบ™เป€เบˆเบฑเบšเบซเบปเบงเบšเบฒเบ‡เบขเปˆเบฒเบ‡. เบ”เบฑเปˆเบ‡โ€‹เบ™เบฑเป‰เบ™โ€‹เบงเบฝเบโ€‹เบ‡เบฒเบ™โ€‹:

เบˆเบธเบ”เบ›เบฐเบชเบปเบ‡

เปƒเบซเป‰เบšเบญเบเบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบ‚เบญเบ‡เบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™:

  • เบชเป‰เบฒเบ‡เบฎเบนเบšเบžเบฒเบšเป€เบžเบตเปˆเบกเป€เบ•เบตเบกเบ‚เบญเบ‡เบฎเบนเบšเปเบšเบšเบ•เปˆเบฒเบ‡เป†เปƒเบ™เบเบฒเบ™เบšเบดเบ™เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เปเบ™เบฐเบ™เปเบฒเบเบฒเบ™เบ—เปเบฒเบ‡เบฒเบ™เป€เบžเบตเปˆเบกเป€เบ•เบตเบกเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเป„เบ”เป‰เบ—เบธเบเป€เบงเบฅเบฒเปƒเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡เบเบฒเบ™เบ—เบตเปˆเบกเบตเบขเบนเปˆเปเบฅเป‰เบงเบ‚เบญเบ‡เบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบ;
  • เบฎเบนเบšเบžเบฒเบšเป€เบžเบตเปˆเบกเป€เบ•เบตเบกเบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบ–เบทเบเบชเป‰เบฒเบ‡เบ‚เบถเป‰เบ™เปƒเบ™เบ—เบธเบเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป;
  • เบ›เบดเบ”เบ„เบงเบฒเบกเบชเบฒเบกเบฒเบ”เปƒเบ™เบเบฒเบ™เบชเป‰เบฒเบ‡เบฎเบนเบšเบžเบฒเบšเป€เบžเบตเปˆเบกเป€เบ•เบตเบกเบ‚เบญเบ‡เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเบšเปเปˆเป„เบ”เป‰เบฅเบฐเบšเบธ.

เบ‚เป‰เบญเบเบˆเบฐเบญเบฐเบ—เบดเบšเบฒเบเบˆเบธเบ”เบชเบธเบ”เบ—เป‰เบฒเบ, เป€เบžเบฒเบฐเบงเปˆเบฒเบกเบฑเบ™เบเบปเบ‡เบเบฑเบ™เบ‚เป‰เบฒเบกเบเบฑเบšเบˆเบธเบ”เบ—เปเบฒเบญเบดเบ”เป€เบฅเบฑเบเบ™เป‰เบญเบ. เบ–เป‰เบฒเบžเบงเบเป€เบฎเบปเบฒเป€เบฎเบฑเบ”เปƒเบซเป‰เบเบฒเบ™เบชเป‰เบฒเบ‡เบฎเบนเบšเบžเบฒเบšเปƒเบ”เป†เป€เบ›เบตเบ”, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบกเบตเบ„เบงเบฒเบกเป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ‚เบญเบ‡เบเบฒเบ™เป‚เบˆเบกเบ•เบตเปƒเบ™เป€เบงเบฑเบšเป„เบŠเบ—เปŒเป‚เบ”เบเบเบฒเบ™เบชเป‰เบฒเบ‡เบˆเปเบฒเบ™เบงเบ™เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเป€เบžเบทเปˆเบญเบ›เบฑเบšเบ‚เบฐเบซเบ™เบฒเบ”เบฎเบนเบšเบžเบฒเบšเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเบšเปเปˆเบกเบตเบ‚เบญเบšเป€เบ‚เบ”, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบŠเปˆเบญเบ‡เป‚เบซเบงเปˆเบ™เบตเป‰เบ•เป‰เบญเบ‡เป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบ›เบดเบ”.

เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบเบฒเบ™เบ•เบดเบ”เบ•เบฑเป‰เบ‡ nginx

เป€เบžเบทเปˆเบญเปเบเป‰เป„เบ‚เบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡, เบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™เบŠเบธเบ”เป‚เบกเบ”เบนเบ™ nginx เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

  • ngx_http_image_filter_module - เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบ›เบฑเบšโ€‹เบ‚เบฐโ€‹เบซเบ™เบฒเบ”โ€‹เบฎเบนเบšโ€‹เบžเบฒเบšโ€‹;
  • ngx_http_proxy_module - เบชเปเบฒเบฅเบฑเบšเบ–เบฒเบ™เบ„เบงเบฒเบกเบˆเปเบฒ;
  • ngx_http_secure_link_module โ€” เป€เบžเบทเปˆเบญเบ›เป‰เบญเบ‡เบเบฑเบ™ spam;

เป‚เบกเบ”เบนเบ™ 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

เบžเบงเบเป€เบฎเบปเบฒเป€เบžเบตเปˆเบกเบญเบฑเบ™เปƒเปเปˆเปƒเบชเปˆเบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเป‚เบฎเบชเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ เบชเบฐเบ–เบฒเบ™เบ—เบตเปˆ เปเบฅเบฐเบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบเบฒเบ™ 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;
        }
...
    }
...

เบžเบงเบเป€เบฎเบปเบฒเบเบฑเบ‡เป€เบžเบตเปˆเบก host เปƒเปเปˆเปƒเบชเปˆ config:

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 โ€” เบกเบตโ€‹เบ„เบงเบฒเบกโ€‹เบญเปˆเบญเบ™โ€‹เป„เบซเบงโ€‹เบเบฑเบšโ€‹เบชเบฐโ€‹เบ–เบฒเบ™โ€‹เบ—เบตเปˆโ€‹เปเบฅเบฐโ€‹เบฅเบฑเบโ€‹เบชเบฐโ€‹เบ™เบฐโ€‹เบžเบฒโ€‹เบชเบฒโ€‹เบฅเบฑเบ”โ€‹เป€เบŠเบโ€‹, เบชเบฐโ€‹เบ™เบฑเป‰เบ™โ€‹เบ‚เป‰เบฒโ€‹เบžเบฐโ€‹เป€เบˆเบปเป‰เบฒโ€‹เป„เบ”เป‰โ€‹เป€เบฎเบฑเบ”โ€‹เปƒเบซเป‰โ€‹เบกเบตโ€‹เป„เบกเป‰โ€‹เบ—เปˆเบญเบ™โ€‹เบ”เป‰เบงเบโ€‹ alias.

เปƒเบŠเป‰เปƒเบ™เปเบญเบฑเบšเบžเบฅเบดเป€เบ„เบŠเบฑเบ™เป€เบงเบฑเบš

เปƒเบ™เบฅเบฐเบ”เบฑเบšเบ„เปเบฒเบฎเป‰เบญเบ‡เบชเบฐเบซเบกเบฑเบเป€เบงเบฑเบšเป„เบŠเบ•เปŒ, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ•เปเปˆเป„เบ›เบ™เบตเป‰ (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'
                );

เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบ‚เป‰เบญเบเบเบฑเบ‡เปเบ™เบฐเบ™เปเบฒเปƒเบซเป‰เบ„เบดเบ”เป„เบฅเปˆเบ‚เบฐเบซเบ™เบฒเบ” preview.

เบซเบงเบฒเบ

เป€เบกเบทเปˆเบญเบฅเบถเบšเบฎเบนเบšเบžเบฒเบšเบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš, เบเบฒเบ™เบชเบฐเปเบ”เบ‡เบ•เบปเบงเบขเปˆเบฒเบ‡, เบ•เบฒเบกเบ—เปเบฒเบกเบฐเบŠเบฒเบ”, เบˆเบฐเบšเปเปˆเบ–เบทเบเบฅเบถเบšเบญเบญเบเบˆเบฒเบ cache เบˆเบปเบ™เบเปˆเบงเบฒ cache เบšเปเปˆเบ–เบทเบเบ•เป‰เบญเบ‡, เปเบฅเบฐเปƒเบ™เบเปเบฅเบฐเบ™เบตเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เบเบฒเบ™เบชเบฐเปเบ”เบ‡เบ•เบปเบงเบขเปˆเบฒเบ‡เบชเบฒเบกเบฒเบ”เบกเบตเบขเบนเปˆเบซเบ™เบถเปˆเบ‡เบกเบทเป‰เบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เบฅเบถเบš, เปเบ•เปˆเบ™เบตเป‰เปเบกเปˆเบ™เป€เบงเบฅเบฒเบชเบนเบ‡เบชเบธเบ”.

เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™