X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=net%2Fhttp.lua;h=b78f84382b40137484b3261ce541ded64c153d27;hb=3f2cecc3e9967a2bb2b6a95c4843cea7a73a22a1;hp=3b783a41c89cefab692f0f29b4bf286065c98452;hpb=5a1000e8e61beb0c9ecf56ad9342d5b7031f9b49;p=prosody.git diff --git a/net/http.lua b/net/http.lua index 3b783a41..b78f8438 100644 --- a/net/http.lua +++ b/net/http.lua @@ -1,12 +1,11 @@ -- Prosody IM -- Copyright (C) 2008-2010 Matthew Wild -- Copyright (C) 2008-2010 Waqas Hussain --- +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -local socket = require "socket" local b64 = require "util.encodings".base64.encode; local url = require "socket.url" local httpstream_new = require "net.http.parser".new; @@ -20,10 +19,11 @@ local t_insert, t_concat = table.insert, table.concat; local pairs = pairs; local tonumber, tostring, xpcall, select, traceback = tonumber, tostring, xpcall, select, debug.traceback; +local assert, error = assert, error local log = require "util.logger".init("http"); -module "http" +local _ENV = nil; local requests = {}; -- Open requests @@ -36,7 +36,7 @@ function listener.onconnect(conn) if req.query then t_insert(request_line, 4, "?"..req.query); end - + conn:write(t_concat(request_line)); local t = { [2] = ": ", [4] = "\r\n" }; for k, v in pairs(req.headers) do @@ -44,7 +44,7 @@ function listener.onconnect(conn) conn:write(t_concat(t)); end conn:write("\r\n"); - + if req.body then conn:write(req.body); end @@ -71,6 +71,17 @@ function listener.ondisconnect(conn, err) requests[conn] = nil; end +function listener.ondetach(conn) + requests[conn] = nil; +end + +local function destroy_request(request) + if request.conn then + request.conn = nil; + request.handler:close() + end +end + local function request_reader(request, data, err) if not request.parser then local function error_cb(reason) @@ -80,12 +91,12 @@ local function request_reader(request, data, err) end destroy_request(request); end - + if not data then error_cb(err); return; end - + local function success_cb(r) if request.callback then request.callback(r.body, r.code, r, request); @@ -102,25 +113,34 @@ local function request_reader(request, data, err) end local function handleerr(err) log("error", "Traceback[http]: %s", traceback(tostring(err), 2)); end -function request(u, ex, callback) +local function request(u, ex, callback) local req = url.parse(u); - + if not (req and req.host) then callback(nil, 0, req); return nil, "invalid-url"; end - + if not req.path then req.path = "/"; end - + local method, headers, body; - + + local host, port = req.host, req.port; + local host_header = host; + if (port == "80" and req.scheme == "http") + or (port == "443" and req.scheme == "https") then + port = nil; + elseif port then + host_header = host_header..":"..port; + end + headers = { - ["Host"] = req.host; + ["Host"] = host_header; ["User-Agent"] = "Prosody XMPP Server"; }; - + if req.userinfo then headers["Authorization"] = "Basic "..b64(req.userinfo); end @@ -140,33 +160,29 @@ function request(u, ex, callback) end end end - + -- Attach to request object req.method, req.headers, req.body = method, headers, body; - + local using_https = req.scheme == "https"; if using_https and not ssl_available then error("SSL not available, unable to contact https URL"); end - local port = tonumber(req.port) or (using_https and 443 or 80); - - -- Connect the socket, and wrap it with net.server - local conn = socket.tcp(); - conn:settimeout(10); - local ok, err = conn:connect(req.host, port); - if not ok and err ~= "timeout" then - callback(nil, 0, req); - return nil, err; - end - + local port_number = port and tonumber(port) or (using_https and 443 or 80); + local sslctx = false; if using_https then - sslctx = ex and ex.sslctx or { mode = "client", protocol = "sslv23", options = { "no_sslv2" } }; + sslctx = ex and ex.sslctx or { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" } }; end - req.handler, req.conn = server.wrapclient(conn, req.host, port, listener, "*a", sslctx); + local handler, conn = server.addclient(host, port_number, listener, "*a", sslctx) + if not handler then + callback(nil, 0, req); + return nil, conn; + end + req.handler, req.conn = handler, conn req.write = function (...) return req.handler:write(...); end - + req.callback = function (content, code, request, response) log("debug", "Calling callback, status %s", code or "---"); return select(2, xpcall(function () return callback(content, code, request, response) end, handleerr)); end req.reader = request_reader; req.state = "status"; @@ -175,17 +191,12 @@ function request(u, ex, callback) return req; end -function destroy_request(request) - if request.conn then - request.conn = nil; - request.handler:close() - end -end - -local urlencode, urldecode = util_http.urlencode, util_http.urldecode; -local formencode, formdecode = util_http.formencode, util_http.formdecode; - -_M.urlencode, _M.urldecode = urlencode, urldecode; -_M.formencode, _M.formdecode = formencode, formdecode; - -return _M; +return { + request = request; + + -- COMPAT + urlencode = util_http.urlencode; + urldecode = util_http.urldecode; + formencode = util_http.formencode; + formdecode = util_http.formdecode; +};