Skip to content

Commit 814fe8b

Browse files
committed
fix: content-type header for metrics endpoints
Issue #13: - JSON endpoints now return the correct Content-Type: `application/json; charset=utf-8`. Additionally: - Added tests to verify the correctness of the Content-Type header. This fix ensures proper header formatting and alignment with client expectations.
1 parent fc13434 commit 814fe8b

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ tags
1010
doc/apidoc/
1111
.idea
1212
*.swp
13+
.DS_Store

Diff for: roles/metrics-export.lua

+11-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,17 @@ end
100100
local http_handlers = {
101101
json = function(req)
102102
local json_exporter = require('metrics.plugins.json')
103-
return req:render({ text = json_exporter.export() })
103+
local json_data = json_exporter.export()
104+
105+
local content_type = 'application/json'
106+
107+
if req.httpd.options.charset then
108+
content_type = string.format('%s; charset=%s', content_type, req.httpd.options.charset)
109+
end
110+
111+
local response = req:render({ text = json_data })
112+
response.headers['content-type'] = content_type
113+
return response
104114
end,
105115
prometheus = function(...)
106116
local http_handler = require('metrics.plugins.prometheus').collect_http

Diff for: test/unit/http_test.lua

+60-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,16 @@ local function assert_json(uri, tls_opts)
5555
local response = http_client:get(uri, tls_opts)
5656
t.assert(response.body)
5757

58-
local data = response.body
59-
local decoded = json.decode(data)
58+
local decoded = json.decode(response.body)
59+
if type(decoded) == 'string' then
60+
decoded = json.decode(decoded)
61+
end
62+
t.assert(#decoded > 0)
63+
if type(decoded) ~= 'table' then
64+
print('Raw response body:', response.body)
65+
end
66+
t.assert(type(decoded) == 'table', 'Response body is not a valid JSON object')
67+
6068
for _, node in ipairs(decoded) do
6169
node.timestamp = nil
6270
end
@@ -1140,3 +1148,53 @@ for name, case in pairs(test_tls_cases) do
11401148
end
11411149
end
11421150
end
1151+
1152+
local function assert_content_type(uri, expected_content_type, tls_opts)
1153+
local response = http_client:get(uri, tls_opts)
1154+
t.assert_equals(response.status, 200)
1155+
t.assert_equals(response.headers['content-type'], expected_content_type)
1156+
end
1157+
1158+
local test_content_type_cases = {
1159+
['json'] = {
1160+
cfg = {
1161+
http = {
1162+
{
1163+
listen = 8081,
1164+
endpoints = {
1165+
{
1166+
path = "/json_metrics",
1167+
format = "json",
1168+
},
1169+
},
1170+
},
1171+
},
1172+
},
1173+
expected_url = "http://127.0.0.1:8081/json_metrics",
1174+
expected_content_type = "application/json; charset=utf-8",
1175+
},
1176+
['prometheus'] = {
1177+
cfg = {
1178+
http = {
1179+
{
1180+
listen = 8081,
1181+
endpoints = {
1182+
{
1183+
path = "/prometheus_metrics",
1184+
format = "prometheus",
1185+
},
1186+
},
1187+
},
1188+
},
1189+
},
1190+
expected_url = "http://127.0.0.1:8081/prometheus_metrics",
1191+
expected_content_type = "text/plain; charset=utf8",
1192+
},
1193+
}
1194+
1195+
for name, case in pairs(test_content_type_cases) do
1196+
g['test_content_type_' .. name] = function(cg)
1197+
cg.role.apply(case.cfg)
1198+
assert_content_type(case.expected_url, case.expected_content_type)
1199+
end
1200+
end

0 commit comments

Comments
 (0)