要求されたファイルが特定のサイズ(たとえば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ジャンプが内部にあるため、アクセスログはクリーンなままです。