【问题标题】:Serve images bigger than minimum file size in Nginx (and lua)在 Nginx(和 lua)中提供大于最小文件大小的图像
【发布时间】:2015-01-29 08:09:36
【问题描述】:

我正在尝试检查请求的文件是否超过特定大小(例如 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
        ';
    }
}

【问题讨论】:

  • no_image_small.png 有多大?它是否小于 250 字节?我不是 nginx 专家,但该错误消息看起来像 nginx 发现处理程序会循环并完全杀死处理程序。
  • no_image_small.png 是 3030 字节,我在 ngx.var.uri 中请求的图像是 17 字节。我会把这个添加到问题中
  • 所以我认为考虑图像大小是错误的。这不是请求处理本身的一部分,它是处理程序的一部分,nginx 在不评估处理程序的情况下无法评估它,我怀疑它是否第二次这样做。尝试不使用与该处理程序模式匹配的文件名。我打赌这会奏效。我认为 nginx 只是看到处理程序正在请求将由自己处​​理的重定向并且不允许这样做。

标签: http nginx lua


【解决方案1】:

您可以读取验证中的 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 跳转是内部的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 2011-09-05
    • 1970-01-01
    • 2011-03-14
    • 2011-02-03
    相关资源
    最近更新 更多