aboutsummaryrefslogtreecommitdiffstats
path: root/net/http.lua
diff options
context:
space:
mode:
Diffstat (limited to 'net/http.lua')
-rw-r--r--net/http.lua53
1 files changed, 44 insertions, 9 deletions
diff --git a/net/http.lua b/net/http.lua
index 7335d210..a13c3942 100644
--- a/net/http.lua
+++ b/net/http.lua
@@ -12,6 +12,8 @@ local httpstream_new = require "net.http.parser".new;
local util_http = require "util.http";
local events = require "util.events";
local verify_identity = require"util.x509".verify_identity;
+local promise = require "util.promise";
+local http_errors = require "net.http.errors";
local basic_resolver = require "net.resolvers.basic";
local connect = require "net.connect".connect;
@@ -22,6 +24,7 @@ local t_insert, t_concat = table.insert, table.concat;
local pairs = pairs;
local tonumber, tostring, traceback =
tonumber, tostring, debug.traceback;
+local os_time = os.time;
local xpcall = require "util.xpcall".xpcall;
local error = error
@@ -40,7 +43,7 @@ local listener = { default_port = 80, default_mode = "*a" };
local function handleerr(err) log("error", "Traceback[http]: %s", traceback(tostring(err), 2)); return err; end
local function log_if_failed(req, ret, ...)
if not ret then
- log("error", "Request '%s': error in callback: %s", req.id, tostring((...)));
+ log("error", "Request '%s': error in callback: %s", req.id, (...));
if not req.suppress_errors then
error(...);
end
@@ -81,7 +84,24 @@ local function request_reader(request, data, err)
return;
end
+ local finalize_sink;
local function success_cb(r)
+ if r.partial then
+ -- Request should be streamed
+ log("debug", "Request '%s': partial response (%s%s)",
+ request.id,
+ r.chunked and "chunked, " or "",
+ r.body_length and ("%d bytes"):format(r.body_length) or "unknown length"
+ );
+ if request.streaming_handler then
+ log("debug", "Request '%s': Streaming via handler");
+ r.body_sink, finalize_sink = request.streaming_handler(r);
+ end
+ return;
+ elseif finalize_sink then
+ log("debug", "Request '%s': Finalizing response stream");
+ finalize_sink(r);
+ end
if request.callback then
request.callback(r.body, r.code, r, request);
request.callback = nil;
@@ -144,13 +164,11 @@ function listener.onconnect(conn)
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
- t[1], t[3] = k, v;
- conn:write(t_concat(t));
+ t_insert(request_line, k .. ": " .. v .. "\r\n");
end
- conn:write("\r\n");
+ t_insert(request_line, "\r\n")
+ conn:write(t_concat(request_line));
if req.body then
conn:write(req.body);
@@ -161,7 +179,7 @@ function listener.onincoming(conn, data)
local request = requests[conn];
if not request then
- log("warn", "Received response from connection %s with no request attached!", tostring(conn));
+ log("warn", "Received response from connection %s with no request attached!", conn);
return;
end
@@ -202,6 +220,7 @@ local function request(self, u, ex, callback)
req.url = u;
req.http = self;
+ req.time = os_time();
if not req.path then
req.path = "/";
@@ -254,6 +273,7 @@ local function request(self, u, ex, callback)
end
req.insecure = ex.insecure;
req.suppress_errors = ex.suppress_errors;
+ req.streaming_handler = ex.streaming_handler;
end
log("debug", "Making %s %s request '%s' to %s", req.scheme:upper(), method or "GET", req.id, (ex and ex.suppress_url and host_header) or u);
@@ -282,7 +302,22 @@ end
local function new(options)
local http = {
options = options;
- request = request;
+ request = function (self, u, ex, callback)
+ if callback ~= nil then
+ return request(self, u, ex, callback);
+ else
+ return promise.new(function (resolve, reject)
+ request(self, u, ex, function (body, code, a, b)
+ if code == 0 then
+ reject(http_errors.new(body, { request = a }));
+ else
+ a.request = b;
+ resolve(a);
+ end
+ end);
+ end);
+ end
+ end;
new = options and function (new_options)
local final_options = {};
for k, v in pairs(options) do final_options[k] = v; end
@@ -297,7 +332,7 @@ local function new(options)
end
local default_http = new({
- sslctx = { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" } };
+ sslctx = { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" }, alpn = "http/1.1" };
suppress_errors = true;
});