From 5b4b9158799293eeaf8439d40a7845b5b0a5e125 Mon Sep 17 00:00:00 2001
From: Diego Nehab
+Note: These constants are global. Changing them will also +change the behavior other code that might be using LuaSocket. +
diff --git a/src/http.lua b/src/http.lua index 45ffa15..d6bcc91 100644 --- a/src/http.lua +++ b/src/http.lua @@ -23,11 +23,14 @@ local _M = socket.http ----------------------------------------------------------------------------- -- connection timeout in seconds _M.TIMEOUT = 60 --- default port for document retrieval -_M.PORT = 80 -- user agent field sent in request _M.USERAGENT = socket._VERSION +-- supported schemes +local SCHEMES = { ["http"] = true } +-- default port for document retrieval +local PORT = 80 + ----------------------------------------------------------------------------- -- Reads MIME headers from a connection, unfolding where needed ----------------------------------------------------------------------------- @@ -114,7 +117,7 @@ function _M.open(host, port, create) h.try = socket.newtry(function() h:close() end) -- set timeout before connecting h.try(c:settimeout(_M.TIMEOUT)) - h.try(c:connect(host, port or _M.PORT)) + h.try(c:connect(host, port or PORT)) -- here everything worked return h end @@ -218,7 +221,7 @@ local function adjustheaders(reqt) } -- if we have authentication information, pass it along if reqt.user and reqt.password then - lower["authorization"] = + lower["authorization"] = "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password)) end -- if we have proxy authentication information, pass it along @@ -226,7 +229,7 @@ local function adjustheaders(reqt) if proxy then proxy = url.parse(proxy) if proxy.user and proxy.password then - lower["proxy-authorization"] = + lower["proxy-authorization"] = "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password)) end end @@ -240,7 +243,7 @@ end -- default url parts local default = { host = "", - port = _M.PORT, + port = PORT, path ="/", scheme = "http" } @@ -250,9 +253,10 @@ local function adjustrequest(reqt) local nreqt = reqt.url and url.parse(reqt.url, default) or {} -- explicit components override url for i,v in base.pairs(reqt) do nreqt[i] = v end - if nreqt.port == "" then nreqt.port = 80 end - socket.try(nreqt.host and nreqt.host ~= "", - "invalid host '" .. base.tostring(nreqt.host) .. "'") + if nreqt.port == "" then nreqt.port = PORT end + if not (nreqt.host and nreqt.host ~= "") then + socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") + end -- compute uri if user hasn't overriden nreqt.uri = reqt.uri or adjusturi(nreqt) -- adjust headers in request @@ -263,9 +267,13 @@ local function adjustrequest(reqt) end local function shouldredirect(reqt, code, headers) - return headers.location and - string.gsub(headers.location, "%s", "") ~= "" and - (reqt.redirect ~= false) and + local location = headers.location + if not location then return false end + location = string.gsub(location, "%s", "") + if location == "" then return false end + local scheme = string.match(location, "^([%w][%w%+%-%.]*)%:") + if scheme and not SCHEMES[scheme] then return false end + return (reqt.redirect ~= false) and (code == 301 or code == 302 or code == 303 or code == 307) and (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") and (not reqt.nredirects or reqt.nredirects < 5) @@ -289,10 +297,10 @@ local trequest, tredirect source = reqt.source, sink = reqt.sink, headers = reqt.headers, - proxy = reqt.proxy, + proxy = reqt.proxy, nredirects = (reqt.nredirects or 0) + 1, create = reqt.create - } + } -- pass location header back as a hint we redirected headers = headers or {} headers.location = headers.location or location @@ -309,7 +317,7 @@ end h:sendheaders(nreqt.headers) -- if there is a body, send it if nreqt.source then - h:sendbody(nreqt.headers, nreqt.source, nreqt.step) + h:sendbody(nreqt.headers, nreqt.source, nreqt.step) end local code, status = h:receivestatusline() -- if it is an HTTP/0.9 server, simply get the body and we are done @@ -319,13 +327,13 @@ end end local headers -- ignore any 100-continue messages - while code == 100 do + while code == 100 do headers = h:receiveheaders() code, status = h:receivestatusline() end headers = h:receiveheaders() -- at this point we should have a honest reply from the server - -- we can't redirect if we already used the source, so we report the error + -- we can't redirect if we already used the source, so we report the error if shouldredirect(nreqt, code, headers) and not nreqt.source then h:close() return tredirect(reqt, headers.location)