Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to index local 'form' (a nil value) #26

Open
zayednetad opened this issue Jun 29, 2016 · 4 comments
Open

Attempt to index local 'form' (a nil value) #26

zayednetad opened this issue Jun 29, 2016 · 4 comments

Comments

@zayednetad
Copy link

zayednetad commented Jun 29, 2016

Hi,
I am following below code on fedora Linux with nginx:

        local resty_sha256 = require "resty.sha256"
        local upload = require "resty.upload"

        local chunk_size = 4096
        local form = upload:new(chunk_size)
        local sha256 = resty_sha256:new()
        local file

        local upload_path = '/tmp/uploads/'


        while true do
           local typ, res, err = form:read()

            if not typ then
                ngx.say("failed to read: ", err)
                return
            end

            if typ == "header" then
                local file_name = upload_path .. ngx.time()
                if file_name then
                    file = io.open(file_name, 'w+')
                    if not file then
                        ngx.say("failed to open file ", file_name)
                        return
                    end
                end
            elseif typ == "body" then
                if file then
                    file:write(res)
                    sha256:update(res)
                end
            elseif typ == "part_end" then
                file:close()
                file = nil
            elseif typ == "eof" then
                break
            else
                -- nothing
            end
        end

        local digest = sha256:final()
        sha256:reset()

        local str = require "resty.string"
        ngx.say("sha256: ", str.to_hex(digest))```

When I run this as

curl -F "[email protected]" http://127.0.0.1:8089/uploadtest

It gives me below errors:

$ tail -f /usr/local/openresty/nginx/logs/error.log 2016/06/29 15:26:23 [error] 31449#0: *12 lua entry thread aborted: runtime error: /usr/local/openresty/nginx/uploadtest.lua:13: attempt to index local 'form' (a nil value) stack traceback: coroutine 0: /usr/local/openresty/nginx/uploadtest.lua: in function </usr/local/openresty/nginx/uploadtest.lua:1>, client: 127.0.0.1, server: localhost, request: "POST /uploadtest HTTP/1.1", host: "127.0.0.1:8089"

Can you please help me what is wrong here?

@agentzh
Copy link
Member

agentzh commented Jun 29, 2016

@zayednetad The new method may fail. You should handle any error returned from it. As in the document example:

                local form, err = upload:new(chunk_size)
                if not form then
                    ngx.log(ngx.ERR, "failed to new upload: ", err)
                    ngx.exit(500)
                end

@zayednetad
Copy link
Author

Now it says below:

2016/07/01 00:14:36 [error] 19582#0: *3 [lua] uploadtest.lua:7: failed to new upload: request body already exists, client: 127.0.0.1, server: localhost, request: "POST /uploadtest HTTP/1.1", host: "127.0.0.1:8089"

@agentzh
Copy link
Member

agentzh commented Jul 1, 2016

The error message clearly indicates that the request body has already been read by something else.

Ensue you do not turn on the lua_need_request_body directive in your nginx.conf and do not call ngx.req.read_body() nor ngx.req.discard_body(), for example. All these would consume the request body before this library can get its hands on it.

@whoszus
Copy link

whoszus commented Sep 22, 2017

With the same issues , but i got nothing like ngx.req.read_body() nor ngx.req.discard_body() in nginx.conf ;what's the next step should i take to resolve it ? Here 's the code

local upload = require "resty.upload"
local cjson = require "cjson"

local chunk_size = 4096
local form ,err = upload:new(chunk_size)
if not form then
    ngx.log(ngx.ERR, "failed to new upload: ", err)
    -- ngx.say(cjson.encode({code=501, msg='ext err', data=res}))
    ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
form:set_timeout(500)
local conf = {max_size=1000000, allow_exts={'jpg', 'png', 'gif'}}
local file
local file_name

function get_ext(res)
    local ext = 'jpg'
    if res == 'image/png' then
        ext = 'png'
    elseif res == 'image/jpg' or res == 'image/jpeg' then
        ext = 'jpg'
    elseif res == 'image/gif' then
        ext = 'gif'
    end
    return ext
end

function getLocalIP()
    os.execute("/sbin/ifconfig|sed -n '/inet addr/s/^[^:]*:\\([0-9.]\\{7,15\\}\\) .*/\\1/p' > ip.info");
    local_ip_list = {}
    local_ip_file = assert(io.open("ip.info", "r"))

    for line in local_ip_file:lines() do
      local_ip_list[#local_ip_list + 1] = line
    end

    local_ip_file:close();
    print(table.concat(local_ip_list,';'));
    ngx.log(ngx.INFO,"ip addr:"..local_ip_list)
    return local_ip_list;
end


local random = math.random
local function uuid()
    local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    return string.gsub(template, '[xy]', function (c)
        local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
        return string.format('%x', v)
    end)
end


local function uuid2()
     local template ="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
     d = io.open("/dev/urandom", "r"):read(4)
     math.randomseed(os.time() + d:byte(1) + (d:byte(2) * 256) + (d:byte(3) * 65536) + (d:byte(4) * 4294967296))
     return string.gsub(template, "x", function (c)
      local v = (c == "x") and math.random(0, 0xf) or math.random(8, 0xb)
      return string.format("%x", v)
      end)
end



function in_array(v, tab)
    local i = false
    for _, val in ipairs(tab) do
        if val == v then
            i = true
            break
        end
    end
    return i
end

function get_filename(res)  
    local filename = ngx.re.match(res,'(.+)filename="(.+)"(.*)')
    if filename then   
        return filename[2]  
    end  
end  

while true do
    local typ, res, err = form:read() 
    if not typ then
        ngx.say(cjson.encode({code=502, msg='failed to read:', data=err}))
        return
    end
    if typ == "header" then
        if res[1] == "Content-Disposition" then
            math.randomseed(tostring(os.time()):reverse():sub(1, 6))
            local file_id = uuid2()
            local extension = get_ext(res[2])
            local fileName = get_filename(res[2])
            ngx.log(ngx.INFO,extension);
            ngx.log(ngx.ERR,filename)
            -- getLocalIP();
            if not extension then
                 ngx.say(cjson.encode({code=501, msg='ext not found', data=res}))
                 return 
            end

            if not in_array(extension, conf.allow_exts) then
                ngx.say(cjson.encode({code=501, msg='deny', data=res}))
                return 
            end

            local dir = '/home/tinker/temp/upload/'..os.date('%Y')..os.date('%m')..os.date('%d')..'/'   
            local status = os.execute('mkdir -p '..dir)
            if status ~= 0 then
                ngx.say(cjson.encode({code=501, msg='mkdir exp'}))
                return
            end  
            file_name = dir..file_id.."."..extension          
            if file_name then
                file = io.open(file_name, "w+")
                if not file then
                    ngx.say(cjson.encode({code=500, msg='failed to open file',imgurl=''}))
                    return
                end
            end
        end
     elseif typ == "body" then
        if type(tonumber(res)) == 'number' and tonumber(res) > conf.max_size then
            ngx.say(cjson.encode({code=501, msg='oversize', data=res}))
            return
        end
        if file then
            file:write(res)            
        end
    elseif typ == "part_end" then
        if file then
            file:close()
            file = nil
        end
    elseif typ == "eof" then
        file_name = string.gsub(file_name, '/home/tinker/temp/upload/', '')

        ngx.say(cjson.encode({code=200, msg='great',imgurl= file_name}))
        break
    else
        
    end
end

this line "ngx.log(ngx.ERR,filename) " logs a nil ;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants