diff --git a/kong/plugins/basicauth/access.lua b/kong/plugins/basicauth/access.lua index cb7c8d21a4c1..b5799efe4274 100644 --- a/kong/plugins/basicauth/access.lua +++ b/kong/plugins/basicauth/access.lua @@ -5,6 +5,11 @@ local constants = require "kong.constants" local _M = {} +local function skip_authentication(headers) + -- Skip upload request that expect a 100 Continue response + return headers["expect"] and stringy.startswith(headers["expect"], "100") +end + -- Fast lookup for credential retrieval depending on the type of the authentication -- -- All methods must respect: @@ -61,6 +66,7 @@ local function validate_credentials(credential, username, password) end function _M.execute(conf) + if not conf or skip_authentication(ngx.req.get_headers()) then return end if not conf then return end local username, password = retrieve_credentials(ngx.req, conf) diff --git a/kong/plugins/filelog/log.lua b/kong/plugins/filelog/log.lua index be07d1aecb57..bec6600f1a69 100644 --- a/kong/plugins/filelog/log.lua +++ b/kong/plugins/filelog/log.lua @@ -4,8 +4,21 @@ local cjson = require "cjson" local _M = {} -function _M.execute() - ngx.log(ngx.INFO, cjson.encode(ngx.ctx.log_message)) +-- Log to a file +-- @param `premature` +-- @param `conf` Configuration table, holds http endpoint details +-- @param `message` Message to be logged +local function log(premature, conf, message) + local f = io.open(conf.path, "a+") + f:write(cjson.encode(message).."\n") + f:close() +end + +function _M.execute(conf) + local ok, err = ngx.timer.at(0, log, conf, ngx.ctx.log_message) + if not ok then + ngx.log(ngx.ERR, "[filelog] failed to create timer: ", err) + end end return _M diff --git a/kong/plugins/filelog/schema.lua b/kong/plugins/filelog/schema.lua index 1ab17e9b997b..de2798b472e7 100644 --- a/kong/plugins/filelog/schema.lua +++ b/kong/plugins/filelog/schema.lua @@ -1 +1,18 @@ -return {} -- No schema \ No newline at end of file +local IO = require "kong.tools.io" + +local function validate_file(value) + local exists = IO.file_exists(value) + if not os.execute("touch "..value) == 0 then + return false, "Cannot create a file in the path specified. Make sure the path is valid, and Kong has the right permissions" + end + + if not exists then + os.remove(value) -- Remove the created file if it didn't exist before + end + + return true +end + +return { + path = { required = true, type = "string", func = validate_file } +} \ No newline at end of file diff --git a/kong/plugins/keyauth/access.lua b/kong/plugins/keyauth/access.lua index ae054642dcb6..8b4101a22c11 100644 --- a/kong/plugins/keyauth/access.lua +++ b/kong/plugins/keyauth/access.lua @@ -11,6 +11,11 @@ local MULTIPART_DATA = "multipart/form-data" local _M = {} +local function skip_authentication(headers) + -- Skip upload request that expect a 100 Continue response + return headers["expect"] and stringy.startswith(headers["expect"], "100") +end + local function get_key_from_query(key_name, request, conf) local key, parameters local found_in = {} @@ -111,7 +116,7 @@ local retrieve_credentials = { } function _M.execute(conf) - if not conf then return end + if not conf or skip_authentication(ngx.req.get_headers()) then return end local credential for _, v in ipairs({ constants.AUTHENTICATION.QUERY, constants.AUTHENTICATION.HEADER }) do diff --git a/kong/resolver/access.lua b/kong/resolver/access.lua index 16eb590c6961..8ccedfd82e2e 100644 --- a/kong/resolver/access.lua +++ b/kong/resolver/access.lua @@ -63,14 +63,9 @@ function _M.execute(conf) -- Setting the backend URL for the proxy_pass directive ngx.var.backend_url = get_backend_url(api)..ngx.var.request_uri - ngx.req.set_header("Host", get_host_from_url(ngx.var.backend_url)) - -- There are some requests whose authentication needs to be skipped - if not skip_authentication(ngx.req.get_headers()) then - -- Saving these properties for the other plugins handlers - ngx.ctx.api = api - end + ngx.ctx.api = api end return _M diff --git a/kong/tools/io.lua b/kong/tools/io.lua index fd370ffccd04..038d839c6491 100644 --- a/kong/tools/io.lua +++ b/kong/tools/io.lua @@ -62,6 +62,13 @@ function _M.write_to_file(path, value) return true end +function _M.file_size(path) + local file = io.open(path, "rb") + local size = file:seek("end") + file:close() + return size +end + function _M.retrieve_files(dir, options) local fs = require "luarocks.fs" local pattern = options.file_pattern diff --git a/spec/plugins/logging_spec.lua b/spec/plugins/logging_spec.lua index 5a76e65d8bf3..f4e0df12c911 100644 --- a/spec/plugins/logging_spec.lua +++ b/spec/plugins/logging_spec.lua @@ -16,6 +16,8 @@ local TCP_PORT = 20777 local UDP_PORT = 20778 local HTTP_PORT = 20779 +local FILE_LOG_PATH = "/tmp/file_log_spec_output.log" + describe("Logging Plugins", function() setup(function() @@ -31,7 +33,7 @@ describe("Logging Plugins", function() { name = "tcplog", value = { host = "127.0.0.1", port = TCP_PORT }, __api = 1 }, { name = "udplog", value = { host = "127.0.0.1", port = UDP_PORT }, __api = 2 }, { name = "httplog", value = { http_endpoint = "http://localhost:"..HTTP_PORT }, __api = 3 }, - { name = "filelog", value = {}, __api = 4 } + { name = "filelog", value = { path = FILE_LOG_PATH }, __api = 4 } } } @@ -97,6 +99,8 @@ describe("Logging Plugins", function() end) it("should log to file", function() + os.remove(FILE_LOG_PATH) + local uuid = string.gsub(uuid(), "-", "") -- Making the request @@ -105,25 +109,12 @@ describe("Logging Plugins", function() ) assert.are.equal(200, status) - -- Reading the log file and finding the line with the entry - local configuration = yaml.load(IO.read_file(TEST_CONF)) - assert.truthy(configuration) - local error_log = IO.read_file(configuration.nginx_working_dir.."/logs/error.log") - local line - local lines = stringy.split(error_log, "\n") - for _, v in ipairs(lines) do - if string.find(v, uuid, nil, true) then - line = v - break - end + while not (IO.file_exists(FILE_LOG_PATH) and IO.file_size(FILE_LOG_PATH) > 0) do + -- Wait for the file to be created, and for the log to be appended end - assert.truthy(line) - - -- Retrieve the JSON part of the line - local json_str = line:match("(%{.*%})") - assert.truthy(json_str) - local log_message = cjson.decode(json_str) + local file_log = IO.read_file(FILE_LOG_PATH) + local log_message = cjson.decode(stringy.strip(file_log)) assert.are.same("127.0.0.1", log_message.client_ip) assert.are.same(uuid, log_message.request.headers.file_log_uuid) end)