From 41fb4a0820687cb7c1f17c2291ac0671dc25c137 Mon Sep 17 00:00:00 2001 From: PidgeyBE Date: Wed, 1 Feb 2023 14:35:41 +0100 Subject: [PATCH 1/8] Fix request buffering for HTTP/2.0 --- kong/runloop/handler.lua | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/kong/runloop/handler.lua b/kong/runloop/handler.lua index 3a7a9434509..529aacb0888 100644 --- a/kong/runloop/handler.lua +++ b/kong/runloop/handler.lua @@ -1280,19 +1280,18 @@ return { return exec("@grpc") end - if protocol_version == 1.1 then - if route.request_buffering == false then - if route.response_buffering == false then - return exec("@unbuffered") - end - - return exec("@unbuffered_request") - end - + if route.request_buffering == false then if route.response_buffering == false then - return exec("@unbuffered_response") + return exec("@unbuffered") end + + return exec("@unbuffered_request") + end + + if route.response_buffering == false then + return exec("@unbuffered_response") end + end end, -- Only executed if the `router` module found a route and allows nginx to proxy it. From c2477716aea9bb50386044941088a26e742b526e Mon Sep 17 00:00:00 2001 From: Pieterjan Date: Tue, 21 Feb 2023 18:49:01 +0000 Subject: [PATCH 2/8] trying to add tests --- .devcontainer/docker-compose.yml | 2 + kong/runloop/handler.lua | 2 +- .../05-proxy/27-unbuffered_spec.lua | 293 ++++++++++++++++++ spec/helpers.lua | 10 +- 4 files changed, 304 insertions(+), 3 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 0b69da3395d..f4b1e5801d6 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -35,6 +35,8 @@ services: KONG_PG_HOST: db OPENSSL_DIR: /usr/local/kong CRYPTO_DIR: /usr/local/kong + # env vars to be able to run tests + KONG_TEST_PG_DATABASE: kong # Overrides default command so things don't shut down after the process ends. command: /bin/sh -c "while sleep 1000; do :; done" diff --git a/kong/runloop/handler.lua b/kong/runloop/handler.lua index 529aacb0888..05af0997512 100644 --- a/kong/runloop/handler.lua +++ b/kong/runloop/handler.lua @@ -105,7 +105,7 @@ local set_upstream_ssl_trusted_store = ktls.set_upstream_ssl_trusted_store if is_http_module then set_authority = require("resty.kong.grpc").set_authority - set_log_level = require("resty.kong.log").set_log_level + --set_log_level = require("resty.kong.log").set_log_level end diff --git a/spec/02-integration/05-proxy/27-unbuffered_spec.lua b/spec/02-integration/05-proxy/27-unbuffered_spec.lua index 5a32aca4911..fd967d05890 100644 --- a/spec/02-integration/05-proxy/27-unbuffered_spec.lua +++ b/spec/02-integration/05-proxy/27-unbuffered_spec.lua @@ -1,7 +1,9 @@ local helpers = require "spec.helpers" local random = require "resty.random" local rstring = require "resty.string" +local cjson = require "cjson" +local timeout = 60000 -- HTTP 1.1 Chunked Body (5 MB) local function body() @@ -23,6 +25,13 @@ local function body() end +--- HTTP 2.0 Body (5 MB) +--- Chunked body's are not really supported by HTTP/2.0 +--- But lua-http converts the chunks into HTTP/2.0 compatible data frames +local function body2() + return rstring.to_hex(random.bytes(100)) +end + for _, strategy in helpers.each_strategy() do describe("HTTP 1.1 Chunked [#" .. strategy .. "]", function() local proxy_client @@ -296,3 +305,287 @@ for _, strategy in helpers.each_strategy() do end) end) end + + +-- Tests for HTTP/2.0 +for _, strategy in helpers.each_strategy() do + describe("HTTP 2.0 Buffered requests/response [#" .. strategy .. "]", function() + local proxy_client + local warmup_client + + lazy_setup(function() + local bp = helpers.get_db_utils(strategy, { + "routes", + "services" + }) + + local service = bp.services:insert() + + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/buffered" }, + request_buffering = true, + response_buffering = true, + service = service, + }) + + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/unbuffered" }, + request_buffering = false, + response_buffering = false, + service = service, + }) + + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/unbuffered-request" }, + request_buffering = false, + response_buffering = true, + service = service, + }) + + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/unbuffered-response" }, + request_buffering = true, + response_buffering = false, + service = service, + }) + + assert(helpers.start_kong { + database = strategy, + nginx_conf = "spec/fixtures/custom_nginx.template", + }) + + end) + + lazy_teardown(function() + helpers.stop_kong() + end) + + before_each(function() + proxy_ip = helpers.get_proxy_ip(true, true) + proxy_port = helpers.get_proxy_port(true, true) + warmup_client = helpers.http2_client(proxy_ip, proxy_port, true) + proxy_client = helpers.http2_client(proxy_ip, proxy_port, true) + end) + + describe("request latency", function() + local buffered_latency + local unbuffered_latency + local unbuffered_request_latency + local unbuffered_response_latency + + it("is calculated for buffered", function() + print("PJ0") + local res, headers = assert(warmup_client { + headers = { + [":method"] = "POST", + [":path"] = "/buffered/post", + }, + body = "warmup" + }) + assert.equal('200', headers:get ":status") + + local res, headers = assert(proxy_client { + headers = { + [":method"] = "POST", + [":path"] = "/buffered/post", + ["content-type"] = "application/octet-stream", + }, + timeout = 10, + body = body2() + }) + + local json = cjson.decode(res) + assert.equal('200', headers:get ":status") + print("HEADERS") + for name, value, never_index in headers:each() do + print(name, " ", value) + end + buffered_latency = tonumber(headers:get("x-kong-proxy-latency")) + assert.is_number(buffered_latency) + end) + + -- it("is calculated for unbuffered", function() + -- warmup_client:post("/unbuffered/post", { body = "warmup" }) + + -- local res = proxy_client:send({ + -- method = "POST", + -- path = "/unbuffered/post", + -- body = body(), + -- headers = { + -- ["Transfer-Encoding"] = "chunked", + -- ["Content-Type"] = "application/octet-stream", + -- } + -- }) + + -- assert.equal(200, res.status) + + -- unbuffered_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) + + -- assert.is_number(unbuffered_latency) + -- end) + + -- it("is calculated for unbuffered request", function() + -- warmup_client:post("/unbuffered-request/post", { body = "warmup" }) + + -- local res = proxy_client:send({ + -- method = "POST", + -- path = "/unbuffered-request/post", + -- body = body(), + -- headers = { + -- ["Transfer-Encoding"] = "chunked", + -- ["Content-Type"] = "application/octet-stream", + -- } + -- }) + + -- assert.equal(200, res.status) + + -- unbuffered_request_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) + + -- assert.is_number(unbuffered_request_latency) + -- end) + + -- it("is calculated for unbuffered response", function() + -- warmup_client:post("/unbuffered-response/post", { body = "warmup" }) + + -- local res = proxy_client:send({ + -- method = "POST", + -- path = "/unbuffered-response/post", + -- body = body(), + -- headers = { + -- ["Transfer-Encoding"] = "chunked", + -- ["Content-Type"] = "application/octet-stream", + -- } + -- }) + + -- assert.equal(200, res.status) + + -- unbuffered_response_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) + + -- assert.is_number(unbuffered_response_latency) + -- end) + + -- it("is greater for buffered than unbuffered", function() + -- assert.equal(true, buffered_latency > unbuffered_latency) + -- end) + + -- it("is greater for buffered than unbuffered request", function() + -- assert.equal(true, buffered_latency > unbuffered_request_latency) + -- end) + + -- it("is greater for unbuffered response than unbuffered", function() + -- assert.equal(true, unbuffered_response_latency > unbuffered_latency) + -- end) + + -- it("is greater for unbuffered response than unbuffered request", function() + -- assert.equal(true, unbuffered_response_latency > unbuffered_request_latency) + -- end) + -- end) + + -- describe("number of response chunks", function() + -- local buffered_chunks = 0 + -- local unbuffered_chunks = 0 + -- local unbuffered_request_chunks = 0 + -- local unbuffered_response_chunks = 0 + + -- it("is calculated for buffered", function() + -- warmup_client:get("/buffered/stream/1") + + -- local res = proxy_client:get("/buffered/stream/1000") + + -- assert.equal(200, res.status) + + -- local reader = res.body_reader + + -- repeat + -- local chunk, err = reader(8192 * 640) + + -- assert.equal(nil, err) + + -- if chunk then + -- buffered_chunks = buffered_chunks + 1 + -- end + -- until not chunk + -- end) + + -- it("is calculated for unbuffered", function() + -- warmup_client:get("/unbuffered/stream/1") + + -- local res = proxy_client:get("/unbuffered/stream/1000") + + -- assert.equal(200, res.status) + + -- local reader = res.body_reader + + -- repeat + -- local chunk, err = reader(8192 * 640) + + -- assert.equal(nil, err) + + -- if chunk then + -- unbuffered_chunks = unbuffered_chunks + 1 + -- end + -- until not chunk + -- end) + + -- it("is calculated for unbuffered request", function() + -- warmup_client:get("/unbuffered-request/stream/1") + + -- local res = proxy_client:get("/unbuffered-request/stream/1000") + + -- assert.equal(200, res.status) + + -- local reader = res.body_reader + + -- repeat + -- local chunk, err = reader(8192 * 640) + + -- assert.equal(nil, err) + + -- if chunk then + -- unbuffered_request_chunks = unbuffered_request_chunks + 1 + -- end + -- until not chunk + -- end) + + -- it("is calculated for unbuffered response", function() + -- warmup_client:get("/unbuffered-response/stream/1") + + -- local res = proxy_client:get("/unbuffered-response/stream/1000") + + -- assert.equal(200, res.status) + + -- local reader = res.body_reader + + -- repeat + -- local chunk, err = reader(8192 * 640) + + -- assert.equal(nil, err) + + -- if chunk then + -- unbuffered_response_chunks = unbuffered_response_chunks + 1 + -- end + -- until not chunk + -- end) + + -- it("is greater for unbuffered than buffered", function() + -- assert.equal(true, unbuffered_chunks > buffered_chunks) + -- end) + + -- it("is greater for unbuffered than unbuffered request", function() + -- assert.equal(true, unbuffered_chunks > unbuffered_request_chunks) + -- end) + + -- it("is greater for unbuffered response than buffered", function() + -- assert.equal(true, unbuffered_response_chunks > buffered_chunks) + -- end) + + -- it("is greater for unbuffered response than unbuffered request", function() + -- assert.equal(true, unbuffered_response_chunks > unbuffered_request_chunks) + -- end) + end) + end) +end \ No newline at end of file diff --git a/spec/helpers.lua b/spec/helpers.lua index 37c8aec27ae..c39708157cb 100644 --- a/spec/helpers.lua +++ b/spec/helpers.lua @@ -1043,13 +1043,19 @@ local function http2_client(host, port, tls) meta.__call = function(req, opts) local headers = opts and opts.headers local timeout = opts and opts.timeout + local req_body = opts and opts.body for k, v in pairs(headers or {}) do req.headers:upsert(k, v) end + + if req_body then + req:set_body(req_body) + end - local headers, stream = req:go(timeout) - local body = stream:get_body_as_string() + local headers, stream = assert(req:go(timeout)) + print("REQ IS SENT") + local body = assert(stream:get_body_as_string()) return body, headers end From 898699d424df5880e831804ac4605d2bc5f8759b Mon Sep 17 00:00:00 2001 From: Pieterjan Date: Wed, 22 Feb 2023 16:32:58 +0000 Subject: [PATCH 3/8] Run tests for both HTTP/1.1 and HTTP/2.0 --- .devcontainer/Dockerfile | 4 +- Makefile | 6 +- .../05-proxy/27-unbuffered_spec.lua | 572 ++++++------------ 3 files changed, 185 insertions(+), 397 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 92016901500..2e0b9e94154 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -9,4 +9,6 @@ RUN apt-get install -y \ unzip \ git \ m4 \ - libyaml-dev + libyaml-dev \ + curl \ + libcurl4-openssl-dev diff --git a/Makefile b/Makefile index d859858eff4..1c8fc1a0218 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ $(info starting make in kong) OS := $(shell uname | awk '{print tolower($$0)}') MACHINE := $(shell uname -m) -DEV_ROCKS = "busted 2.1.1" "busted-htest 1.0.0" "luacheck 1.1.0" "lua-llthreads2 0.1.6" "http 0.4" "ldoc 1.4.6" +DEV_ROCKS = "busted 2.1.1" "busted-htest 1.0.0" "luacheck 1.1.0" "lua-llthreads2 0.1.6" "http 0.4" "ldoc 1.4.6" "Lua-cURL 0.3.13" WIN_SCRIPTS = "bin/busted" "bin/kong" "bin/kong-health" BUSTED_ARGS ?= -v TEST_CMD ?= bin/busted $(BUSTED_ARGS) @@ -12,10 +12,12 @@ ifeq ($(OS), darwin) OPENSSL_DIR ?= $(shell brew --prefix)/opt/openssl GRPCURL_OS ?= osx YAML_DIR ?= $(shell brew --prefix)/opt/libyaml +CURL_INCDIR ?= /usr/include/x86_64-linux-gnu/ else OPENSSL_DIR ?= /usr GRPCURL_OS ?= $(OS) YAML_DIR ?= /usr +CURL_INCDIR ?= /usr/include/x86_64-linux-gnu/ endif ifeq ($(MACHINE), aarch64) @@ -164,7 +166,7 @@ dependencies: bin/grpcurl echo $$rock already installed, skipping ; \ else \ echo $$rock not found, installing via luarocks... ; \ - luarocks install $$rock OPENSSL_DIR=$(OPENSSL_DIR) CRYPTO_DIR=$(OPENSSL_DIR) || exit 1; \ + luarocks install $$rock OPENSSL_DIR=$(OPENSSL_DIR) CRYPTO_DIR=$(OPENSSL_DIR) CURL_INCDIR=$(CURL_INCDIR) || exit 1; \ fi \ done; diff --git a/spec/02-integration/05-proxy/27-unbuffered_spec.lua b/spec/02-integration/05-proxy/27-unbuffered_spec.lua index fd967d05890..5817c8f69d6 100644 --- a/spec/02-integration/05-proxy/27-unbuffered_spec.lua +++ b/spec/02-integration/05-proxy/27-unbuffered_spec.lua @@ -1,37 +1,56 @@ local helpers = require "spec.helpers" local random = require "resty.random" local rstring = require "resty.string" -local cjson = require "cjson" - -local timeout = 60000 - --- HTTP 1.1 Chunked Body (5 MB) -local function body() - local chunk = "2000" .."\r\n" .. rstring.to_hex(random.bytes(4096)) .. "\r\n" - local i = 0 - return function() - i = i + 1 - - if i == 641 then - return "0\r\n\r\n" - end - - if i == 642 then - return nil - end - - return chunk +local curl = require("cURL") + +local HTTP_VERSIONS = { + CURL_HTTP_VERSION_NONE = 0, + CURL_HTTP_VERSION_1_0 = 1, + CURL_HTTP_VERSION_1_1 = 2, + CURL_HTTP_VERSION_2_0 = 3, + CURL_HTTP_VERSION_2TLS = 4, + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE = 5 +} + +local function curl_post(url, body, http_version) + http_version = http_version or HTTP_VERSIONS["CURL_HTTP_VERSION_2_0"] + + local c = curl.easy{ + url = url, + ssl_verifypeer = false, + ssl_verifyhost = false, + post = true, + postfields = body, + --[curl.OPT_VERBOSE] = true, + [curl.OPT_HEADER] = true, + [curl.OPT_HTTP_VERSION] = http_version, + } + local response = {} + c:setopt_writefunction(table.insert, response) + c:perform() + + local status = c:getinfo_response_code() + local full_response = table.concat(response) + local raw_headers = string.sub(full_response, 1, c:getinfo(curl.INFO_HEADER_SIZE)) + local return_body = string.sub(full_response, c:getinfo(curl.INFO_HEADER_SIZE)) + + --parse headers + local return_headers = {} + for header in string.gmatch(raw_headers, "[%w%-]+:[^\n]+") do + local index = string.find(header, ":") + return_headers[string.lower(string.sub(header, 1, index-1))] = string.sub(header, index+2) end + + return status, return_headers, return_body end ---- HTTP 2.0 Body (5 MB) ---- Chunked body's are not really supported by HTTP/2.0 ---- But lua-http converts the chunks into HTTP/2.0 compatible data frames +--- HTTP Body (5 MB) local function body2() - return rstring.to_hex(random.bytes(100)) + return rstring.to_hex(random.bytes(5*1024*1024/2)) end + for _, strategy in helpers.each_strategy() do describe("HTTP 1.1 Chunked [#" .. strategy .. "]", function() local proxy_client @@ -98,109 +117,6 @@ for _, strategy in helpers.each_strategy() do proxy_client:close() end) - describe("request latency", function() - local buffered_latency - local unbuffered_latency - local unbuffered_request_latency - local unbuffered_response_latency - - it("is calculated for buffered", function() - warmup_client:post("/buffered/post", { body = "warmup" }) - - local res = proxy_client:send({ - method = "POST", - path = "/buffered/post", - body = body(), - headers = { - ["Transfer-Encoding"] = "chunked", - ["Content-Type"] = "application/octet-stream", - } - }) - - assert.equal(200, res.status) - - buffered_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - assert.is_number(buffered_latency) - end) - - it("is calculated for unbuffered", function() - warmup_client:post("/unbuffered/post", { body = "warmup" }) - - local res = proxy_client:send({ - method = "POST", - path = "/unbuffered/post", - body = body(), - headers = { - ["Transfer-Encoding"] = "chunked", - ["Content-Type"] = "application/octet-stream", - } - }) - - assert.equal(200, res.status) - - unbuffered_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - assert.is_number(unbuffered_latency) - end) - - it("is calculated for unbuffered request", function() - warmup_client:post("/unbuffered-request/post", { body = "warmup" }) - - local res = proxy_client:send({ - method = "POST", - path = "/unbuffered-request/post", - body = body(), - headers = { - ["Transfer-Encoding"] = "chunked", - ["Content-Type"] = "application/octet-stream", - } - }) - - assert.equal(200, res.status) - - unbuffered_request_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - assert.is_number(unbuffered_request_latency) - end) - - it("is calculated for unbuffered response", function() - warmup_client:post("/unbuffered-response/post", { body = "warmup" }) - - local res = proxy_client:send({ - method = "POST", - path = "/unbuffered-response/post", - body = body(), - headers = { - ["Transfer-Encoding"] = "chunked", - ["Content-Type"] = "application/octet-stream", - } - }) - - assert.equal(200, res.status) - - unbuffered_response_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - assert.is_number(unbuffered_response_latency) - end) - - it("is greater for buffered than unbuffered", function() - assert.equal(true, buffered_latency > unbuffered_latency) - end) - - it("is greater for buffered than unbuffered request", function() - assert.equal(true, buffered_latency > unbuffered_request_latency) - end) - - it("is greater for unbuffered response than unbuffered", function() - assert.equal(true, unbuffered_response_latency > unbuffered_latency) - end) - - it("is greater for unbuffered response than unbuffered request", function() - assert.equal(true, unbuffered_response_latency > unbuffered_request_latency) - end) - end) - describe("number of response chunks", function() local buffered_chunks = 0 local unbuffered_chunks = 0 @@ -307,285 +223,153 @@ for _, strategy in helpers.each_strategy() do end --- Tests for HTTP/2.0 -for _, strategy in helpers.each_strategy() do - describe("HTTP 2.0 Buffered requests/response [#" .. strategy .. "]", function() - local proxy_client - local warmup_client - - lazy_setup(function() - local bp = helpers.get_db_utils(strategy, { - "routes", - "services" - }) +-- Tests for HTTP/1.1 and HTTP/2.0 +local versions_to_test = {"CURL_HTTP_VERSION_1_1", "CURL_HTTP_VERSION_2_0"} +for _, version in pairs(versions_to_test) do + local http_version = HTTP_VERSIONS[version] - local service = bp.services:insert() + for _, strategy in helpers.each_strategy() do + describe("HTTP 2.0 Buffered requests/response [#" .. strategy .. "] [#"..version.."]", function() + local warmup_client + local base_url + local proxy_ip + local proxy_port - bp.routes:insert({ - protocols = { "http", "https" }, - paths = { "/buffered" }, - request_buffering = true, - response_buffering = true, - service = service, - }) - - bp.routes:insert({ - protocols = { "http", "https" }, - paths = { "/unbuffered" }, - request_buffering = false, - response_buffering = false, - service = service, - }) - - bp.routes:insert({ - protocols = { "http", "https" }, - paths = { "/unbuffered-request" }, - request_buffering = false, - response_buffering = true, - service = service, - }) - - bp.routes:insert({ - protocols = { "http", "https" }, - paths = { "/unbuffered-response" }, - request_buffering = true, - response_buffering = false, - service = service, - }) - - assert(helpers.start_kong { - database = strategy, - nginx_conf = "spec/fixtures/custom_nginx.template", - }) + lazy_setup(function() + local bp = helpers.get_db_utils(strategy, { + "routes", + "services" + }) - end) + local service = bp.services:insert() - lazy_teardown(function() - helpers.stop_kong() - end) + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/buffered" }, + request_buffering = true, + response_buffering = true, + service = service, + }) - before_each(function() - proxy_ip = helpers.get_proxy_ip(true, true) - proxy_port = helpers.get_proxy_port(true, true) - warmup_client = helpers.http2_client(proxy_ip, proxy_port, true) - proxy_client = helpers.http2_client(proxy_ip, proxy_port, true) - end) + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/unbuffered" }, + request_buffering = false, + response_buffering = false, + service = service, + }) - describe("request latency", function() - local buffered_latency - local unbuffered_latency - local unbuffered_request_latency - local unbuffered_response_latency + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/unbuffered-request" }, + request_buffering = false, + response_buffering = true, + service = service, + }) - it("is calculated for buffered", function() - print("PJ0") - local res, headers = assert(warmup_client { - headers = { - [":method"] = "POST", - [":path"] = "/buffered/post", - }, - body = "warmup" + bp.routes:insert({ + protocols = { "http", "https" }, + paths = { "/unbuffered-response" }, + request_buffering = true, + response_buffering = false, + service = service, }) - assert.equal('200', headers:get ":status") - - local res, headers = assert(proxy_client { - headers = { - [":method"] = "POST", - [":path"] = "/buffered/post", - ["content-type"] = "application/octet-stream", - }, - timeout = 10, - body = body2() + + assert(helpers.start_kong { + database = strategy, + nginx_conf = "spec/fixtures/custom_nginx.template", }) - local json = cjson.decode(res) - assert.equal('200', headers:get ":status") - print("HEADERS") - for name, value, never_index in headers:each() do - print(name, " ", value) - end - buffered_latency = tonumber(headers:get("x-kong-proxy-latency")) - assert.is_number(buffered_latency) end) - -- it("is calculated for unbuffered", function() - -- warmup_client:post("/unbuffered/post", { body = "warmup" }) - - -- local res = proxy_client:send({ - -- method = "POST", - -- path = "/unbuffered/post", - -- body = body(), - -- headers = { - -- ["Transfer-Encoding"] = "chunked", - -- ["Content-Type"] = "application/octet-stream", - -- } - -- }) - - -- assert.equal(200, res.status) - - -- unbuffered_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - -- assert.is_number(unbuffered_latency) - -- end) - - -- it("is calculated for unbuffered request", function() - -- warmup_client:post("/unbuffered-request/post", { body = "warmup" }) - - -- local res = proxy_client:send({ - -- method = "POST", - -- path = "/unbuffered-request/post", - -- body = body(), - -- headers = { - -- ["Transfer-Encoding"] = "chunked", - -- ["Content-Type"] = "application/octet-stream", - -- } - -- }) - - -- assert.equal(200, res.status) - - -- unbuffered_request_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - -- assert.is_number(unbuffered_request_latency) - -- end) - - -- it("is calculated for unbuffered response", function() - -- warmup_client:post("/unbuffered-response/post", { body = "warmup" }) - - -- local res = proxy_client:send({ - -- method = "POST", - -- path = "/unbuffered-response/post", - -- body = body(), - -- headers = { - -- ["Transfer-Encoding"] = "chunked", - -- ["Content-Type"] = "application/octet-stream", - -- } - -- }) - - -- assert.equal(200, res.status) - - -- unbuffered_response_latency = tonumber(res.headers["X-Kong-Proxy-Latency"]) - - -- assert.is_number(unbuffered_response_latency) - -- end) - - -- it("is greater for buffered than unbuffered", function() - -- assert.equal(true, buffered_latency > unbuffered_latency) - -- end) - - -- it("is greater for buffered than unbuffered request", function() - -- assert.equal(true, buffered_latency > unbuffered_request_latency) - -- end) - - -- it("is greater for unbuffered response than unbuffered", function() - -- assert.equal(true, unbuffered_response_latency > unbuffered_latency) - -- end) - - -- it("is greater for unbuffered response than unbuffered request", function() - -- assert.equal(true, unbuffered_response_latency > unbuffered_request_latency) - -- end) - -- end) - - -- describe("number of response chunks", function() - -- local buffered_chunks = 0 - -- local unbuffered_chunks = 0 - -- local unbuffered_request_chunks = 0 - -- local unbuffered_response_chunks = 0 - - -- it("is calculated for buffered", function() - -- warmup_client:get("/buffered/stream/1") - - -- local res = proxy_client:get("/buffered/stream/1000") - - -- assert.equal(200, res.status) - - -- local reader = res.body_reader - - -- repeat - -- local chunk, err = reader(8192 * 640) - - -- assert.equal(nil, err) - - -- if chunk then - -- buffered_chunks = buffered_chunks + 1 - -- end - -- until not chunk - -- end) - - -- it("is calculated for unbuffered", function() - -- warmup_client:get("/unbuffered/stream/1") - - -- local res = proxy_client:get("/unbuffered/stream/1000") - - -- assert.equal(200, res.status) - - -- local reader = res.body_reader - - -- repeat - -- local chunk, err = reader(8192 * 640) - - -- assert.equal(nil, err) - - -- if chunk then - -- unbuffered_chunks = unbuffered_chunks + 1 - -- end - -- until not chunk - -- end) - - -- it("is calculated for unbuffered request", function() - -- warmup_client:get("/unbuffered-request/stream/1") - - -- local res = proxy_client:get("/unbuffered-request/stream/1000") - - -- assert.equal(200, res.status) - - -- local reader = res.body_reader - - -- repeat - -- local chunk, err = reader(8192 * 640) - - -- assert.equal(nil, err) - - -- if chunk then - -- unbuffered_request_chunks = unbuffered_request_chunks + 1 - -- end - -- until not chunk - -- end) - - -- it("is calculated for unbuffered response", function() - -- warmup_client:get("/unbuffered-response/stream/1") - - -- local res = proxy_client:get("/unbuffered-response/stream/1000") - - -- assert.equal(200, res.status) - - -- local reader = res.body_reader - - -- repeat - -- local chunk, err = reader(8192 * 640) - - -- assert.equal(nil, err) - - -- if chunk then - -- unbuffered_response_chunks = unbuffered_response_chunks + 1 - -- end - -- until not chunk - -- end) - - -- it("is greater for unbuffered than buffered", function() - -- assert.equal(true, unbuffered_chunks > buffered_chunks) - -- end) - - -- it("is greater for unbuffered than unbuffered request", function() - -- assert.equal(true, unbuffered_chunks > unbuffered_request_chunks) - -- end) + lazy_teardown(function() + warmup_client:close() + helpers.stop_kong() + end) - -- it("is greater for unbuffered response than buffered", function() - -- assert.equal(true, unbuffered_response_chunks > buffered_chunks) - -- end) + before_each(function() + proxy_ip = helpers.get_proxy_ip(true, true) + proxy_port = helpers.get_proxy_port(true, true) + warmup_client = helpers.proxy_client() + base_url = "https://" .. proxy_ip .. ":" .. proxy_port + end) - -- it("is greater for unbuffered response than unbuffered request", function() - -- assert.equal(true, unbuffered_response_chunks > unbuffered_request_chunks) - -- end) - end) - end) + describe("request latency", function() + local buffered_latency + local unbuffered_latency + local unbuffered_request_latency + local unbuffered_response_latency + local status, headers, _ + + + it("is calculated for buffered", function() + warmup_client:post("/buffered/post", { body = "warmup" }) + + status, headers, _ = curl_post( + base_url .. "/buffered/post", body2(), + http_version + ) + assert.equal(200, status) + + buffered_latency = tonumber(headers["x-kong-proxy-latency"]) + assert.is_number(buffered_latency) + + end) + + it("is calculated for unbuffered", function() + warmup_client:post("/unbuffered/post", { body = "warmup" }) + + status, headers, _ = curl_post( + base_url .. "/unbuffered/post", body2(), + http_version + ) + assert.equal(200, status) + unbuffered_latency = tonumber(headers["x-kong-proxy-latency"]) + assert.is_number(unbuffered_latency) + + end) + + it("is calculated for unbuffered request", function() + warmup_client:post("/unbuffered-request/post", { body = "warmup" }) + + status, headers, _ = curl_post( + base_url .. "/unbuffered-request/post", body2(), + http_version + ) + assert.equal(200, status) + unbuffered_request_latency = tonumber(headers["x-kong-proxy-latency"]) + assert.is_number(unbuffered_request_latency) + + end) + + it("is calculated for unbuffered response", function() + warmup_client:post("/unbuffered-response/post", { body = "warmup" }) + + status, headers, _ = curl_post( + base_url .. "/unbuffered-response/post", body2(), + http_version + ) + assert.equal(200, status) + unbuffered_response_latency = tonumber(headers["x-kong-proxy-latency"]) + assert.is_number(unbuffered_response_latency) + end) + + it("is greater for buffered than unbuffered", function() + assert.equal(true, buffered_latency > unbuffered_latency) + end) + + it("is greater for buffered than unbuffered request", function() + assert.equal(true, buffered_latency > unbuffered_request_latency) + end) + + it("is greater for unbuffered response than unbuffered", function() + assert.equal(true, unbuffered_response_latency > unbuffered_latency) + end) + + it("is greater for unbuffered response than unbuffered request", function() + assert.equal(true, unbuffered_response_latency > unbuffered_request_latency) + end) + end) + end) + end end \ No newline at end of file From 8fd39fc1fd581434188978196b0a17a2928db9c2 Mon Sep 17 00:00:00 2001 From: Pieterjan Date: Wed, 22 Feb 2023 16:37:21 +0000 Subject: [PATCH 4/8] revert non-relevant changes --- kong/runloop/handler.lua | 2 +- spec/02-integration/05-proxy/27-unbuffered_spec.lua | 10 +++++----- spec/helpers.lua | 6 ++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/kong/runloop/handler.lua b/kong/runloop/handler.lua index 05af0997512..529aacb0888 100644 --- a/kong/runloop/handler.lua +++ b/kong/runloop/handler.lua @@ -105,7 +105,7 @@ local set_upstream_ssl_trusted_store = ktls.set_upstream_ssl_trusted_store if is_http_module then set_authority = require("resty.kong.grpc").set_authority - --set_log_level = require("resty.kong.log").set_log_level + set_log_level = require("resty.kong.log").set_log_level end diff --git a/spec/02-integration/05-proxy/27-unbuffered_spec.lua b/spec/02-integration/05-proxy/27-unbuffered_spec.lua index 5817c8f69d6..36a720afec6 100644 --- a/spec/02-integration/05-proxy/27-unbuffered_spec.lua +++ b/spec/02-integration/05-proxy/27-unbuffered_spec.lua @@ -46,7 +46,7 @@ end --- HTTP Body (5 MB) -local function body2() +local function body() return rstring.to_hex(random.bytes(5*1024*1024/2)) end @@ -306,7 +306,7 @@ for _, version in pairs(versions_to_test) do warmup_client:post("/buffered/post", { body = "warmup" }) status, headers, _ = curl_post( - base_url .. "/buffered/post", body2(), + base_url .. "/buffered/post", body(), http_version ) assert.equal(200, status) @@ -320,7 +320,7 @@ for _, version in pairs(versions_to_test) do warmup_client:post("/unbuffered/post", { body = "warmup" }) status, headers, _ = curl_post( - base_url .. "/unbuffered/post", body2(), + base_url .. "/unbuffered/post", body(), http_version ) assert.equal(200, status) @@ -333,7 +333,7 @@ for _, version in pairs(versions_to_test) do warmup_client:post("/unbuffered-request/post", { body = "warmup" }) status, headers, _ = curl_post( - base_url .. "/unbuffered-request/post", body2(), + base_url .. "/unbuffered-request/post", body(), http_version ) assert.equal(200, status) @@ -346,7 +346,7 @@ for _, version in pairs(versions_to_test) do warmup_client:post("/unbuffered-response/post", { body = "warmup" }) status, headers, _ = curl_post( - base_url .. "/unbuffered-response/post", body2(), + base_url .. "/unbuffered-response/post", body(), http_version ) assert.equal(200, status) diff --git a/spec/helpers.lua b/spec/helpers.lua index c39708157cb..08f6dec8230 100644 --- a/spec/helpers.lua +++ b/spec/helpers.lua @@ -1043,7 +1043,6 @@ local function http2_client(host, port, tls) meta.__call = function(req, opts) local headers = opts and opts.headers local timeout = opts and opts.timeout - local req_body = opts and opts.body for k, v in pairs(headers or {}) do req.headers:upsert(k, v) @@ -1053,9 +1052,8 @@ local function http2_client(host, port, tls) req:set_body(req_body) end - local headers, stream = assert(req:go(timeout)) - print("REQ IS SENT") - local body = assert(stream:get_body_as_string()) + local headers, stream = req:go(timeout) + local body = stream:get_body_as_string() return body, headers end From f845ba525ea02613619fdf33ece08c0963a3a57f Mon Sep 17 00:00:00 2001 From: Pieterjan Date: Wed, 22 Feb 2023 16:37:38 +0000 Subject: [PATCH 5/8] revert non-relevant changes --- spec/helpers.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/helpers.lua b/spec/helpers.lua index 08f6dec8230..37c8aec27ae 100644 --- a/spec/helpers.lua +++ b/spec/helpers.lua @@ -1047,10 +1047,6 @@ local function http2_client(host, port, tls) for k, v in pairs(headers or {}) do req.headers:upsert(k, v) end - - if req_body then - req:set_body(req_body) - end local headers, stream = req:go(timeout) local body = stream:get_body_as_string() From 9d2589feb48a87af1fc8490821bf697e5f4d464b Mon Sep 17 00:00:00 2001 From: Pieterjan Date: Wed, 22 Feb 2023 16:51:31 +0000 Subject: [PATCH 6/8] add curl-dev dependency --- .devcontainer/Dockerfile | 1 - .github/workflows/build_and_test.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2e0b9e94154..4a1cc8a6781 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -10,5 +10,4 @@ RUN apt-get install -y \ git \ m4 \ libyaml-dev \ - curl \ libcurl4-openssl-dev diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 94c7625c52f..aaeac87f44f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -43,7 +43,7 @@ jobs: - name: Install packages if: steps.cache-deps.outputs.cache-hit != 'true' - run: sudo apt update && sudo apt install libyaml-dev valgrind libprotobuf-dev + run: sudo apt update && sudo apt install libyaml-dev valgrind libprotobuf-dev libcurl4-openssl-dev - name: Build Kong if: steps.cache-deps.outputs.cache-hit != 'true' From bcf9ccf1078e5ae4cafa50e0d968be0bfdf50063 Mon Sep 17 00:00:00 2001 From: PidgeyBE Date: Thu, 30 Mar 2023 18:54:48 +0200 Subject: [PATCH 7/8] Update Makefile with bungle's suggestion Co-authored-by: Aapo Talvensaari --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a2cfe9ee2bb..6b3c478ab2d 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ ifeq ($(OS), darwin) OPENSSL_DIR ?= $(shell brew --prefix)/opt/openssl GRPCURL_OS ?= osx YAML_DIR ?= $(shell brew --prefix)/opt/libyaml -CURL_INCDIR ?= /usr/include/x86_64-linux-gnu/ +CURL_INCDIR ?= $(shell brew --prefix)/opt/curl/include/curl else OPENSSL_DIR ?= /usr GRPCURL_OS ?= $(OS) From 5dccea9aeb1dab6ca5656a3ea273b1b5c64dd5fa Mon Sep 17 00:00:00 2001 From: PidgeyBE Date: Thu, 30 Mar 2023 23:37:24 +0200 Subject: [PATCH 8/8] Fix curl dir for macos Co-authored-by: Aapo Talvensaari --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6b3c478ab2d..b0fe66d5c8c 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ ifeq ($(OS), darwin) OPENSSL_DIR ?= $(shell brew --prefix)/opt/openssl GRPCURL_OS ?= osx YAML_DIR ?= $(shell brew --prefix)/opt/libyaml -CURL_INCDIR ?= $(shell brew --prefix)/opt/curl/include/curl +CURL_INCDIR ?= $(shell brew --prefix)/opt/curl/include else OPENSSL_DIR ?= /usr GRPCURL_OS ?= $(OS)