Question

I am trying to get the info CURLINFO_RESPONSE_CODE and CURLINFO_CONTENT_TYPE with curl_easy_getinfo, but both tries seem to fail.

Like in a LuaJit/scanf example, I'm allocating ffi.new("int[1]") to get one element as a pointer and use it as argument, to read the value after it's saved.

ffi = require "ffi"

url = [[http://static02.mediaite.com/geekosystem/uploads/2013/12/doge.jpg]]

ffi.cdef [[
    int curl_version();
    void *curl_easy_init();
    int curl_easy_setopt(void *curl, int option, ...);
    int curl_easy_perform(void *curl);
    void curl_easy_cleanup(void *curl);
    int curl_easy_getinfo(void *curl, int info, ...);
]]

function curl_callback(ptr, size, nmemb, userdata)
    print("Data callback! File-ID: ", userdata, "\n")
    return size*nmemb
end

ffi_curl_callback = ffi.cast("size_t (*)(char *ptr, size_t size, size_t nmemb, void *userdata)", curl_callback)

CURLOPT_URL = 10002
CURLOPT_WRITEFUNCTION = 20011
CURLOPT_VERBOSE = 41
CURLOPT_PROGRESSDATA = 10057
CURLOPT_NOPROGRESS = 43
CURLOPT_WRITEDATA = 10001
CURLE_OK = 0

CURLINFO_RESPONSE_CODE = 2097154
CURLINFO_CONTENT_TYPE = 1048594

libcurl = ffi.load("libcurl.dll")

-- print("cURL Version: ", libcurl.curl_version(), "\n")

curl = libcurl.curl_easy_init()

if curl then

    file = ffi.new("int", 0xabc) -- not needed

    print("Trying to download: ", url, "\n")
    libcurl.curl_easy_setopt(curl, CURLOPT_VERBOSE, ffi.new("long", 1))
    libcurl.curl_easy_setopt(curl, CURLOPT_URL, url)
    libcurl.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ffi_curl_callback)
    --libcurl.curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1)
    --libcurl.curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, 123)
    libcurl.curl_easy_setopt(curl, CURLOPT_WRITEDATA, ffi.cast("void *", file))

    -- bug fixed, called curl_easy_getinfo before curl_easy_perform
    result = libcurl.curl_easy_perform(curl)
    if result == CURLE_OK then
        response_code = ffi.new("int[1]")
        content_type = ffi.new("char*[1]")
        libcurl.curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, response_code)
        libcurl.curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, content_type)
        print("RESPONSE CODE: '", tonumber(response_code[0]), "'\n")
        print("CONTENT TYPE: '", ffi.string(content_type[0]), "'\n")
    else
        print("Error! Result: ", result, "\n")
    end

    libcurl.curl_easy_cleanup(curl)
end

The output is (old output from error):

Data callback! File-ID:         cdata<void *>: 0x00000abc
Data callback! File-ID:         cdata<void *>: 0x00000abc
Data callback! File-ID:         cdata<void *>: 0x00000abc
Data callback! File-ID:         cdata<void *>: 0x00000abc
Data callback! File-ID:         cdata<void *>: 0x00000abc
Data callback! File-ID:         cdata<void *>: 0x00000abc
Result:         0
RESPONSE CODE: '        nil     '
CONTENT TYPE: '         '

Result 0 means CURLE_OK and the file is really downloaded (I've tested that with my custom game FS functions). Though I just cannot get the Response-Code nor Content-Type. Does anybody have an idea what I am doing wrong?

Was it helpful?

Solution

From the docs:

CURLINFO_RESPONSE_CODE

Pass a pointer to a long to receive the last received HTTP, FTP or SMTP response code.

CURLINFO_CONTENT_TYPE

Pass a pointer to a char pointer to receive the content-type of the downloaded object. This is the value read from the Content-Type: field. If you get NULL, it means that the server didn't send a valid Content-Type header or that the protocol used doesn't support this.

These options are asking for long* and char**; you're passing in int* and char*. The following should work:

local resp = ffi.new("long[1]")  -- long*
local err  = libcurl.curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, resp)
local code = ffi.new("char*[1]") -- char**
local err2 = libcurl.curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, code)
-- get the values
resp = tonumber(resp[0])
code = ffi.string(code[0])

Also, if those commented-out calls to curl_easy_setopt aren't working, it's because you're passing an int instead of a long:

local vb  = ffi.new("long", 1)
local err = libcurl.curl_easy_setopt(curl, CURLOPT_VERBOSE, vb)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top