Changeset f291bb5ab0ef376b5f15b11df991efb2cdaeabc1

Show
Ignore:
Timestamp:
06/07/12 14:54:33 (3 years ago)
Author:
Philip Maddox <pmaddox@circonus.com>
git-committer:
Philip Maddox <pmaddox@circonus.com> 1339080873 +0000
git-parent:

[3293ee08096be6695ed4e0d941b63915532da5a5]

git-author:
Philip Maddox <pmaddox@circonus.com> 1339080873 +0000
Message:

Added vastly improved cookie support and fixed some bugs with redirect when the given URI is not an absolute path

Files:

Legend:

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

    r43e571f rf291bb5  
    8686    local lasthdr 
    8787    local str = self.e:read("\n"); 
     88    local cookie_count = 1; 
    8889    if str == nil then error("no response") end 
    8990    self.protocol, self.code = string.match(str, "^HTTP/(%d.%d)%s+(%d+)%s+") 
     
    9192    self.code = tonumber(self.code) 
    9293    self.headers = {} 
     94    self.cookies = {} 
    9395    while true do 
    9496        local str = self.e:read("\n") 
     
    104106        else 
    105107            hdr = string.lower(hdr) 
    106             self.headers[hdr] = val 
     108            if hdr == "set-cookie" then 
     109                self.cookies[cookie_count] = val; 
     110                cookie_count = cookie_count + 1; 
     111            else 
     112                self.headers[hdr] = val 
     113            end 
    107114            lasthdr = hdr 
    108115        end 
    109116    end 
    110     if self.hooks.headers ~= nil then self.hooks.headers(self.headers) end 
     117    if self.hooks.headers ~= nil then self.hooks.headers(self.headers, self.cookies) end 
    111118end 
    112119 
  • src/modules-lua/noit/module/http.lua

    r3293ee0 rf291bb5  
    155155 
    156156function populate_cookie_jar(cookies, host, hdr) 
     157    local path = nil 
    157158    if hdr ~= nil then 
    158159        local name, value, trailer = 
     
    160161        if name ~= nil then 
    161162            local jar = { } 
    162             jar.name = name; 
    163             jar.value = value; 
    164             for k, v in string.gmatch(trailer, "%s*(%w+)(=%w+)?;?") do 
    165                 if v == nil then jar[string.lower(k)] = true 
    166                 else jar[string.lower(k)] = v:sub(2) 
     163            local fields = noit.extras.split(trailer, ";") 
     164            if fields ~= nil then 
     165                for k, v in pairs(fields) do 
     166                    local pair = noit.extras.split(v, "=", 1); 
     167                    if pair ~= nil and pair[1] ~= nil and pair[2] ~= nil then 
     168                        local name = (string.gsub(pair[1], "^%s*(.-)%s*$", "%1")); 
     169                        local setting = (string.gsub(pair[2], "^%s*(.-)%s*$", "%1")); 
     170                        if name == "path" then 
     171                            path = setting 
     172                        end 
     173                    end 
    167174                end 
    168175            end 
    169             if jar.domain ~= nil then host = jar.domain end 
    170             if cookies[host] == nil then cookies[host] = { } end 
    171             table.insert(cookies[host], jar) 
     176            if string.sub(name, 1, 1) ~= ";" and string.sub(value, 1, 1) ~= ";" then 
     177                if path == nil then path = "/" end 
     178                if cookies[host] == nil then cookies[host] = { } end 
     179                if cookies[host][path] == nil then cookies[host][path] = { } end 
     180                jar.name = name 
     181                jar.value = value 
     182                table.insert(cookies[host][path], jar) 
     183            end 
    172184        end 
    173185    end 
     
    187199 
    188200function apply_cookies(headers, cookies, host, uri) 
    189     for h, jars in pairs(cookies) do 
     201    local use_cookies = { } 
     202    for h, paths in pairs(cookies) do 
    190203        if has_host(h, host) then 
    191             for i, jar in ipairs(jars) do 
    192                 if jar.path == nil or 
    193                    uri:sub(1, jar.path:len()) == jar.path then 
    194                     if headers["Cookie"] == nil then 
    195                         headers["Cookie"] = jar.name .. "=" .. jar.value 
    196                     else 
    197                         headers["Cookie"] = headers["Cookie"] .. "; " .. 
    198                                             jar.name .. "=" .. jar.value 
     204            local split_uri = noit.extras.split(uri, "/") 
     205            if split_uri ~= nil then 
     206                local path = "" 
     207                for i, val in pairs(split_uri) do 
     208                    local append = true 
     209                    if val == nil then val = "" end 
     210                    if #split_uri == i and string.find(val, "%.") ~= nil then append = false end 
     211                    if append == true then 
     212                        path = path .. "/" .. val 
     213                        if string.len(path) >= 2 and string.sub(path, 1, 2) == "//" then 
     214                            path = string.sub(path, 2) 
     215                        end 
     216                    end 
     217                    if path == "" then path = "/" end 
     218                    local rindex = string.match(path, '.*()'..'%?') 
     219                    if rindex ~= nil then 
     220                        path = string.sub(path, 1, rindex-1) 
     221                    end 
     222                    if path ~= "/" then 
     223                        while string.find(path, "/", -1) ~= nil do 
     224                            path = string.sub(path, 1, -2) 
     225                        end 
     226                    end 
     227                    if paths[path] ~= nil then 
     228                        local jars = paths[path] 
     229                        for index, jar in ipairs(jars) do 
     230                            use_cookies[jar.name] = jar.value 
     231                        end 
    199232                    end 
    200233                end 
     
    202235        end 
    203236    end 
     237    for name, value in pairs(use_cookies) do 
     238        if headers["Cookie"] == nil then 
     239            headers["Cookie"] = name .. "=" .. value 
     240        else 
     241            headers["Cookie"] = headers["Cookie"] .. "; " .. name .. "=" .. value 
     242        end 
     243    end 
     244end 
     245 
     246function get_new_uri(old_uri, new_uri) 
     247    if new_uri == nil then return "/" end 
     248    if new_uri == "/" then return new_uri end 
     249    local toReturn = old_uri 
     250    while string.find(toReturn, "/", -1) ~= nil do 
     251        toReturn = string.sub(toReturn, 1, -2) 
     252    end 
     253    if string.sub(new_uri, 1, 1) == '?' then 
     254        local rindex = string.match(toReturn, '.*()'.."/") 
     255        toReturn = string.sub(toReturn, 1, rindex-1) 
     256        toReturn = toReturn .. new_uri 
     257    elseif string.sub(new_uri, 1, 1) ~= "." then  
     258        toReturn = new_uri 
     259    else 
     260        toReturn = string.gsub(toReturn, "%/%?", "?") 
     261        while string.sub(new_uri, 1, 1) == "." do 
     262            if string.find(new_uri, "%./") == 1 then 
     263                new_uri = string.gsub("%./", "", 1) 
     264            elseif string.find(new_uri, "%.%./") == 1 then 
     265                --strip out last bit from toReturn 
     266                local rindex = string.match(toReturn, '.*()'.."/") 
     267                toReturn = string.sub(toReturn, 1, rindex-1) 
     268                new_uri = string.gsub(new_uri, "../", "", 1) 
     269            else 
     270                -- bad URI... just return / 
     271                return "/" 
     272            end 
     273        end 
     274        toReturn = toReturn .. "/" .. new_uri 
     275    end 
     276    return toReturn 
     277end 
     278 
     279function get_absolute_path(uri) 
     280    if uri == nil then return "/" end 
     281    local toReturn = uri 
     282    local go_back = string.find(toReturn, "%.%./") 
     283    while go_back ~= nil do 
     284        local tojoin = go_back + 3 
     285        go_back = go_back - 2 
     286        local back_substring = string.sub(toReturn, 1, go_back) 
     287        local forward_substring = string.sub(toReturn, tojoin) 
     288        local rindex = string.match(back_substring, '.*()' .. "/") 
     289        if rindex ~= nil then 
     290            toReturn = string.sub(toReturn, 1, rindex) .. forward_substring 
     291        end 
     292        go_back = string.find(toReturn, "%.%./") 
     293    end 
     294    toReturn = string.gsub(toReturn, "%./", "") 
     295    return toReturn 
    204296end 
    205297 
     
    263355        output = output .. (str or '') 
    264356    end 
    265     callbacks.headers = function (hdrs
     357    callbacks.headers = function (hdrs, setcookies
    266358        next_location = hdrs.location 
    267         populate_cookie_jar(cookies, host, hdrs["set-cookie"]) 
    268         populate_cookie_jar(cookies, hdrs["set-cookie2"]) 
     359        for key, value in pairs(setcookies) do 
     360            populate_cookie_jar(cookies, host, value) 
     361        end 
    269362    end 
    270363 
     
    363456            local prev_port = port 
    364457            local prev_host = host 
     458            local prev_uri = uri 
    365459            method = 'GET' 
    366460            payload = nil 
     
    371465                port = prev_port 
    372466                host = prev_host 
    373                 uri = next_location 
     467                uri = get_new_uri(prev_uri, next_location) 
    374468            elseif schema == 'http' then 
    375469                use_ssl = false 
     
    379473                if port == "" then port = 443 end 
    380474            end 
     475            uri = get_absolute_path(uri) 
    381476            if host ~= nil then 
    382477                headers.Host = host 
     
    387482                end 
    388483                target = r.a 
     484            end 
     485            while string.find(host, "/", -1) ~= nil do 
     486                host = string.sub(host, 1, -2) 
    389487            end 
    390488            headers["Cookie"] = check.config["header_Cookie"]