Changeset 85377e0b5fe246ecd22fff6a4efb1894fc3af77d

Show
Ignore:
Timestamp:
04/21/10 02:45:55 (9 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1271817955 +0000
git-parent:

[220f29f3f3e69addb451afcb396087f4e18a931f]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1271817955 +0000
Message:

support redirects, fixes #270

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/modules-lua/noit/module/http.lua

    r54c26d5 r85377e0  
    199199end 
    200200 
     201function populate_cookie_jar(cookies, host, hdr) 
     202    if hdr ~= nil then 
     203        local name, value, trailer = 
     204            string.match(hdr, "([^=]+)=([^;]+)\;?%s*(.*)") 
     205        if name ~= nil then 
     206            local jar = { } 
     207            jar.name = name; 
     208            jar.value = value; 
     209            for k, v in string.gmatch(trailer, "%s*(%w+)(=%w+)?;?") do 
     210                if v == nil then jar[string.lower(k)] = true 
     211                else jar[string.lower(k)] = v:sub(2) 
     212                end 
     213            end 
     214            if jar.domain ~= nil then host = jar.domain end 
     215            if cookies[host] == nil then cookies[host] = { } end 
     216            table.insert(cookies[host], jar) 
     217        end 
     218    end 
     219end 
     220 
     221function has_host(pat, host) 
     222    if pat == host then return true end 
     223    if pat:sub(1,1) ~= "." then return false end 
     224    local revpat = pat:sub(2):reverse() 
     225    local revhost = host:reverse() 
     226    if revpat == revhost then return true end 
     227    if revpat == revhost:sub(1, revpat:len()) then 
     228        if revhost:sub(pat:len(), pat:len()) == "." then return true end 
     229    end 
     230    return false 
     231end 
     232 
     233function apply_cookies(headers, cookies, host, uri) 
     234    for h, jars in pairs(cookies) do 
     235        if has_host(h, host) then 
     236            for i, jar in ipairs(jars) do 
     237                if jar.path == nil or 
     238                   uri:sub(1, jar.path:len()) == jar.path then 
     239                    if headers["Cookie"] == nil then 
     240                        headers["Cookie"] = jar.name .. "=" .. jar.value 
     241                    else 
     242                        headers["Cookie"] = headers["Cookie"] .. "; " .. 
     243                                            jar.name .. "=" .. jar.value 
     244                    end 
     245                end 
     246            end 
     247        end 
     248    end 
     249end 
     250 
    201251function initiate(module, check) 
    202252    local url = check.config.url or 'http:///' 
     
    208258    local method = check.config.method or "GET" 
    209259    local max_len = 80 
     260    local redirects = check.config.redirects or 0 
    210261 
    211262    -- expect the worst 
     
    234285    local output = '' 
    235286    local connecttime, firstbytetime 
     287    local next_location 
     288    local cookies = { } 
    236289 
    237290    -- callbacks from the HttpClient 
     
    241294        output = output .. (str or '') 
    242295    end 
     296    callbacks.headers = function (hdrs) 
     297        next_location = hdrs.location 
     298        populate_cookie_jar(cookies, host, hdrs["set-cookie"]) 
     299        populate_cookie_jar(cookies, hdrs["set-cookie2"]) 
     300    end 
     301 
    243302    callbacks.connected = function () connecttime = noit.timeval.now() end 
    244303 
     
    309368 
    310369    -- perform the request 
    311     local client = HttpClient:new(callbacks) 
    312     local rv, err = client:connect(check.target, port, use_ssl) 
    313     
    314     if rv ~= 0 then 
    315         check.status(err or "unknown error") 
    316         return 
    317     end 
    318     client:do_request(method, uri, headers, check.config.payload) 
    319     client:get_response() 
     370    local client 
     371    local dns = noit.dns() 
     372    local target = check.target 
     373    local payload = check.config.payload 
     374    -- artificially increase redirects as the initial request counts 
     375    redirects = redirects + 1 
     376    repeat 
     377        starttime = noit.timeval.now() 
     378        local optclient = HttpClient:new(callbacks) 
     379        local rv, err = optclient:connect(target, port, use_ssl) 
     380        
     381        if rv ~= 0 then 
     382            check.status(err or "unknown error") 
     383            return 
     384        end 
     385        optclient:do_request(method, uri, headers, payload) 
     386        optclient:get_response() 
     387 
     388        redirects = redirects - 1 
     389        client = optclient 
     390 
     391        if next_location ~= nil then 
     392            -- reset some stuff for the redirect 
     393            local prev_port = port 
     394            local prev_host = host 
     395            method = 'GET' 
     396            payload = nil 
     397            schema, host, port, uri = 
     398                string.match(next_location, 
     399                             "^(https?)://([^:/]*):?([0-9]*)(/?.*)$") 
     400            if schema == nil then 
     401                port = prev_port 
     402                host = prev_host 
     403                uri = next_location 
     404            elseif schema == 'http' then  
     405                use_ssl = false 
     406                port = port or 80 
     407            elseif schema == 'https' then 
     408                use_ssl = true 
     409                port = port or 443 
     410            end 
     411            if host ~= nil then 
     412                headers.Host = host 
     413                local r = dns:lookup(host) 
     414                if r.a == nil then 
     415                    check.status("failed to resolve " + host) 
     416                    return 
     417                end 
     418                target = r.a 
     419            end 
     420            headers["Cookie"] = check.config["header_Cookie"] 
     421            apply_cookies(headers, cookies, host, uri) 
     422        end 
     423    until redirects <= 0 or next_location == nil 
    320424 
    321425    local endtime = noit.timeval.now()