diff options
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | lib/gitano/actions.lua | 89 |
2 files changed, 44 insertions, 49 deletions
@@ -22,3 +22,7 @@ Gitano depends on [lua-scrypt], [Luxio], [Lace], [Supple], [Gall] and [Clod]. In addition, Gitano depends on the Lua PCRE package lrexlib which can typically be found in lua-rex-pcre or liblua5.1-rex-pcre0 in Debian or Ubuntu. + +If you wish to use the http access capability in post-recive hooks then you +will need to ensure cURL is installed and the `curl` binary itself is present +on your PATH. diff --git a/lib/gitano/actions.lua b/lib/gitano/actions.lua index 30f93de..06b5af7 100644 --- a/lib/gitano/actions.lua +++ b/lib/gitano/actions.lua @@ -10,6 +10,7 @@ local gall = require "gall" local config = require "gitano.config" local sio = require 'luxio.simple' local supple = require 'gitano.supple' +local subprocess = require 'luxio.subprocess' local function update_actions(conf, repo, tags) @@ -41,54 +42,43 @@ local function update_actions(conf, repo, tags) return true end -local function http_txn(method, host, path, headers, body) - log.ddebug("Attempting to fetch",host,":", path) - log.ddebug("Connect...") - local port = "http" - if host:match(":") then - host, port = host:match("^(.-):([^:]+)$") +local function curl_txn(url, headers, body, content_type) + local method = (body and body ~= "") and "POST" or "GET" + local args = { "curl", "--max-filesize", tostring(1024*1024), + "--insecure", "-X", method, "-D-", "-s" } + if type(url) ~= "string" then + return "500", "url must be a string", {}, "" end - local sock, err = sio.connect(host, port) - if not sock then - return "500", err, {}, "" + if url:sub(1,7) ~= "http://" and url:sub(1,8) ~= "https://" then + return "500", "url must be http:// or https://", {}, "" end - local req_lines = { - method .. " " .. path .. " HTTP/1.0", - "Host: " .. host, - } - for k, v in pairs(headers) do - req_lines[#req_lines+1] = ("%s: %s"):format(k,v) + headers = headers or {} + if type(headers) ~= "table" then + return "500", "headers must be a table if provided", {} , "" end - req_lines[#req_lines+1] = "Connection: Close" - req_lines[#req_lines+1] = "" - req_lines[#req_lines+1] = "" - local req = table.concat(req_lines, "\r\n") - log.ddebug("Write request") - log.ddebug(req) - local ok, msg = sock:write(req) - if not ok then - sock:close() - return "500", msg, {}, "" + if method == "POST" then + headers["Content-Type"] = content_type or application/octet-stream + headers["Content-Length"] = tostring(#body) + args[#args+1] = "--data-binary" + args[#args+1] = "@-" end - if body and body ~= "" then - log.ddebug("Writing body of request:") - log.ddebug(body) - ok, msg = sock:write(body) - if not ok then - sock:close() - return "500", msg, {}, "" - end + for k, v in pairs(headers) do + args[#args+1] = "-H" + args[#args+1] = tostring(k) .. ": " .. tostring(v) end - log.ddebug("Read response") - ok, msg = sock:read "*a" - if not ok then - sock:close() - return "500", msg, {}, "" + args[#args+1] = url + args.stdin = body or "" + args.stdout = subprocess.PIPE + args.stderr = subprocess.PIPE + local proc = subprocess.spawn_simple(args) + local response = proc.stdout:read("*a") + local err = proc.stderr:read("*a") + proc.stdout:close() + proc.stderr:close() + local how, why = proc:wait() + if (how ~= "exit" or why ~= 0) then + return "500", err, {}, "" end - local response = ok - - sock:close() - local code, msg, _headers, content = response:match("^HTTP/1.[01] (...) ?([^\r\n]+)\r?\n(.-)\r?\n\r?\n(.*)$") local headers = {} for k, v in _headers:gmatch("([^:\r\n]+): *([^\r\n]+)") do @@ -100,16 +90,15 @@ local function http_txn(method, host, path, headers, body) return code, msg, headers, content end + local function http_get(host, path) - return http_txn("GET", host, path, {}, "") + log.warn("Hook using legacy http_get or http.get, please update to use new fetch() interface") + return curl_txn("http://" .. host .. path) end local function http_post(host, path, content_type, body) - return http_txn("POST", host, path, - { - ["Content-Type"] = content_type, - ["Content-Length"] = tostring(#body), - }, body) + log.warn("Hook using legacy http.post, please update to use new fetch() interface") + return curl_txn("http://" .. host .. path, body, content_type) end local function set_supple_globals(action) @@ -124,7 +113,9 @@ local function set_supple_globals(action) globs["log"] = logcopy if action == "post-receive" then globs["http_get"] = http_get -- Legacy name for this, use http.get - globs["http"] = { get = http_get, post = http_post } + local http_tab = { get = http_get, post = http_post } -- Moar legacy for now + globs["http"] = http_tab + globs["fetch"] = curl_txn end supple.set_globals(globs) end |