Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[fix/alf_serializer] always ensure mimeType is a string #626

Merged
merged 2 commits into from
Oct 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions kong/plugins/log-serializers/alf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@
-- - ngx_http_core_module: http://wiki.nginx.org/HttpCoreModule#.24http_HEADER

local stringy = require "stringy"
local table_insert = table.insert
local tostring = tostring
local pairs = pairs
local ipairs = ipairs
local type = type
local tonumber = tonumber
local string_len = string.len
local os_date = os.date


local EMPTY_ARRAY_PLACEHOLDER = "__empty_array_placeholder__"

Expand All @@ -38,7 +47,7 @@ local function dic_to_array(hash, fn)
for _, val in ipairs(v) do
k = tostring(k)
val = tostring(val)
table.insert(arr, {name = k, value = val})
table_insert(arr, {name = k, value = val})
fn(k, val)
end
end
Expand All @@ -50,6 +59,26 @@ local function dic_to_array(hash, fn)
end
end

--- Get a header from nginx's headers
-- Make sure that is multiple headers of a same name are present,
-- we only want the last one. Also include a default value if
-- no header is present.
-- @param `headers` ngx's request or response headers table.
-- @param `name` Name of the desired header to retrieve.
-- @param `default` String returned in case no header is found.
-- @return `header` The header value (a string) or the default, or nil.
local function get_header(headers, name, default)
local val = headers[name]
if val ~= nil then
if type(val) == "table" then
val = val[#val]
end
return val
end

return default
end

local _M = {}

-- Serialize `ngx` into one ALF entry.
Expand Down Expand Up @@ -108,15 +137,15 @@ function _M.serialize_entry(ngx)

local alf_req_headers_arr = dic_to_array(req_headers, function(k, v) req_headers_str = req_headers_str..k..v end)
local alf_res_headers_arr = dic_to_array(res_headers, function(k, v) res_headers_str = res_headers_str..k..v end)
local alf_req_headers_size = string.len(req_headers_str)
local alf_res_headers_size = string.len(res_headers_str)
local alf_req_headers_size = string_len(req_headers_str)
local alf_res_headers_size = string_len(res_headers_str)

-- mimeType, defaulting to "application/octet-stream"
local alf_req_mimeType = req_headers["Content-Type"] and req_headers["Content-Type"] or "application/octet-stream"
local alf_res_mimeType = res_headers["Content-Type"] and res_headers["Content-Type"] or "application/octet-stream"
local alf_req_mimeType = get_header(req_headers, "Content-Type", "application/octet-stream")
local alf_res_mimeType = get_header(res_headers, "Content-Type", "application/octet-stream")

return {
startedDateTime = os.date("!%Y-%m-%dT%TZ", alf_started_at),
startedDateTime = os_date("!%Y-%m-%dT%TZ", alf_started_at),
time = alf_time,
request = {
method = ngx.req.get_method(),
Expand All @@ -126,7 +155,7 @@ function _M.serialize_entry(ngx)
headers = alf_req_headers_arr,
headersSize = alf_req_headers_size,
cookies = {EMPTY_ARRAY_PLACEHOLDER},
bodySize = string.len(alf_req_body),
bodySize = string_len(alf_req_body),
postData = {
mimeType = alf_req_mimeType,
params = dic_to_array(alf_req_post_args),
Expand Down
5 changes: 5 additions & 0 deletions spec/plugins/mashape-analytics/alf_serializer_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ describe("ALF serializer", function()
assert.are.sameEntry(fixtures.MULTIPLE_UPSTREAMS.ENTRY, entry)
assert.equal(60468, entry.timings.wait)
end)

it("should return the last header if two are present for mimeType", function()
local entry = ALFSerializer.serialize_entry(fixtures.MULTIPLE_HEADERS.NGX_STUB)
assert.are.sameEntry(fixtures.MULTIPLE_HEADERS.ENTRY, entry)
end)
end)

describe("#new_alf()", function ()
Expand Down
94 changes: 94 additions & 0 deletions spec/plugins/mashape-analytics/fixtures/requests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,99 @@ return {
wait = 60468
}
}
},
["MULTIPLE_HEADERS"] = {
["NGX_STUB"] = {
req = {
start_time = function() return 1432844571.623 end,
get_method = function() return "GET" end,
http_version = function() return 1.1 end,
get_headers = function() return {["Accept"] = "/*/", ["Host"] = "mockbin.com", ["Content-Type"] = {"application/json", "application/www-form-urlencoded"}} end,
get_uri_args = function() return {["hello"] = "world", ["foo"] = "bar"} end
},
resp = {
get_headers = function() return {["Connection"] = "close", ["Content-Type"] = {"application/json", "application/www-form-urlencoded"}, ["Content-Length"] = "934"} end
},
status = 200,
var = {
scheme = "http",
host = "mockbin.com",
request_uri = "/request",
request_length = 123,
body_bytes_sent = 934,
remote_addr = "127.0.0.1",
upstream_response_time = "0.391"
},
ctx = {
proxy_started_at = 1432844571719,
proxy_ended_at = 143284457211,
analytics = {
req_body = "hello=world&hello=earth",
res_body = "{\"message\":\"response body\"}",
req_post_args = {["hello"] = {"world", "earth"}},
response_received = 143284457211
}
}
},
["ENTRY"] = {
cache = {},
request = {
bodySize = 23,
cookies = {EMPTY_ARRAY_PLACEHOLDER},
headers = {
{name = "Accept", value = "/*/"},
{name = "Host", value = "mockbin.com"},
{name = "Content-Type", value = "application/json"},
{name = "Content-Type", value = "application/www-form-urlencoded"}
},
headersSize = 95,
httpVersion = "HTTP/1.1",
method = "GET",
postData = {
mimeType = "application/www-form-urlencoded",
params = {
{name = "hello", value = "world"},
{name = "hello", value = "earth"}
},
text = "hello=world&hello=earth"
},
queryString = {
{name = "foo", value = "bar"},
{name = "hello", value = "world"}
},
url = "http://mockbin.com/request"
},
response = {
bodySize = 934,
content = {
mimeType = "application/www-form-urlencoded",
size = 934,
text = "{\"message\":\"response body\"}"
},
cookies = {EMPTY_ARRAY_PLACEHOLDER},
headers = {
{name = "Content-Length", value = "934"},
{name = "Content-Type", value = "application/json"},
{name = "Content-Type", value = "application/www-form-urlencoded"},
{name = "Connection", value = "close"}
},
headersSize = 103,
httpVersion = "",
redirectURL = "",
status = 200,
statusText = ""
},
startedDateTime = "2015-05-28T20:22:51Z",
time = 487,
timings = {
blocked = -1,
connect = -1,
dns = -1,
receive = 0,
send = 96,
ssl = -1,
wait = 391
}
}
}
}