http - Nginx(およびlua)で最小ファイルサイズより大きい画像を提供する

原文 http nginx lua

要求されたファイルが特定のサイズ(たとえば250バイト)を超えているかどうかを確認し、そうであればファイルを提供します。そうでない場合はデフォルトの画像を提供します。

ただし、予期しない結果が出ます。行の長さをチェックするボディの長さが守られていないようで、no_image_small.pngが提供されます。 res.status == 200は機能するようですが、


リクエスト画像サイズ:17バイト
no_image_small.pngサイズ:3030バイト


nginxエラーログ:

2014/12/01 11:52:57 [error] 6033#0: *1 subrequests cycle while processing "/images/blue_image_small.jpg", client: 127.0.0.1, server: images.dev, request: "GET /images/blue_image_small.jpg HTTP/1.1", subrequest: "/images/blue_image_small.jpg", host: "images.dev:8080"
2014/12/01 11:52:57 [error] 6033#0: *1 lua entry thread aborted: runtime error: rewrite_by_lua:2: failed to issue subrequest: -1
stack traceback:
coroutine 0:
    [C]: in function 'capture'
    rewrite_by_lua:2: in function <rewrite_by_lua:1>, client: 127.0.0.1, server: images.dev, request: "GET /images/blue_image_small.jpg HTTP/1.1", subrequest: "/images/blue_image_small.jpg", host: "images.dev:8080"


私のnginx設定:

server {
    listen 8080;
    server_name images.dev www.images.dev;
    root  /home/syz/dev/images/;


    location ~* ^/images/(.*_small.) {
        rewrite_by_lua '
            local res = ngx.location.capture(ngx.var.uri)
            if res.status == 200 then
                local blength = string.len(res.body)
                if blength > 250 then
                    ngx.say(res.body)
                    ngx.exit(ngx.OK)
                else
                    ngx.redirect("/images/no_image.small.png")
                end
            else
                ngx.redirect("/images/no_image_small.png")
            end
        ';
    }
}
答え
応答本文の長さをキャプチャして読み取る代わりに、検証時にContent-Lengthヘッダーを読み取ることができます(より高速です)。

私は本番環境で同様の検証を行っています。

location ~*/img/.*\.(png|jpg|jpeg) {            
           set $max_image_size 15000;
           # default redirect if requested image too big
           error_page 412 = @default_image_loc; 

           #serving the content                   
           root  /local_server/root/;        

           #validating response
           header_filter_by_lua ' 
             local image_size = tonumber(ngx.header.content_length)                
             if image_size > tonumber(ngx.var.max_image_size) then
               ngx.log(ngx.NOTICE, string.format("invalid image size <%s>" , image_size))
               ngx.exit(412)
             end 
          '; 
}

location @default_image_loc {            
        try_files "/img/default_image.png" @none;            
}


412ジャンプが内部にあるため、アクセスログはクリーンなままです。
関連記事

performance - 無限スクロールクエリ結果のREST API

http - CloudFront署名付きURLが403 Forbiddenエラーをスローする[重複]

http - wso2 emmがHTTPSではなくHTTPを使用する

http - PythonでFirefox WebDriverとSeleniumを接続する際の問題

jquery - コントローラから解決されたパラメータを渡すことができません

html - 不適切な参照URL-原因は何ですか?

macos - ChromeがERR_EMPTY_RESPONSEを返すとき、どういうわけかhttps://を明示的に入力する必要があります

python - Squidプロキシは、PythonではなくcurlではないGETリクエストで501を返します

java - Firefox / ChromeとJava GZIPOutputStream間のGZIP / Deflateエラー

c# - 非同期OAuth要求の応答を読み取ろうとすると、System.Net.Http.Formatting.dllで未処理のFileNotFound例外が発生する