Skip to content

Commit 88e9897

Browse files
committed
expose text Content-Type in embedded http server
1 parent 1c6d97b commit 88e9897

2 files changed

Lines changed: 43 additions & 24 deletions

File tree

reporters/kamon-prometheus/src/main/scala/kamon/prometheus/embeddedhttp/SunEmbeddedHttpServer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class SunEmbeddedHttpServer(hostname: String, port: Int, path: String, scrapeSou
4141
val bytes = data.getBytes(StandardCharsets.UTF_8)
4242
var os: OutputStream = null
4343
try {
44+
httpExchange.getResponseHeaders.set("Content-Type", "text/plain; charset=UTF-8")
4445
if (shouldUseCompression(httpExchange)) {
4546
httpExchange.getResponseHeaders.set("Content-Encoding", "gzip")
4647
httpExchange.sendResponseHeaders(200, 0)
@@ -51,7 +52,7 @@ class SunEmbeddedHttpServer(hostname: String, port: Int, path: String, scrapeSou
5152
httpExchange.sendResponseHeaders(200, bytes.length)
5253
os.write(bytes)
5354
}
54-
} finally Option(os).map(_.close())
55+
} finally Option(os).foreach(_.close())
5556
} else httpExchange.sendResponseHeaders(404, -1)
5657
}
5758
}

reporters/kamon-prometheus/src/test/scala/kamon/prometheus/EmbeddedHttpServerSpec.scala

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import org.scalatest.matchers.should.Matchers
77
import org.scalatest.wordspec.AnyWordSpec
88

99
import java.io.FileNotFoundException
10-
import java.net.URL
10+
import java.net.{URL, URLConnection}
1111
import java.util.zip.GZIPInputStream
12+
import scala.jdk.CollectionConverters._
1213

1314
class SunHttpServerSpecSuite extends EmbeddedHttpServerSpecSuite {
1415
override def testConfig: Config = ConfigFactory.load()
@@ -32,7 +33,7 @@ abstract class EmbeddedHttpServerSpecSuite extends AnyWordSpec
3233
"the embedded sun http server" should {
3334
"provide no data comment on GET to /metrics when no data loaded yet" in {
3435
// act
35-
val metrics = httpGetMetrics("/metrics")
36+
val metrics = httpGetMetrics("/metrics").content
3637
// assert
3738
metrics shouldBe "# The kamon-prometheus module didn't receive any data just yet.\n"
3839
}
@@ -41,7 +42,7 @@ abstract class EmbeddedHttpServerSpecSuite extends AnyWordSpec
4142
// arrange
4243
testee.reportPeriodSnapshot(emptyPeriodSnapshot)
4344
// act
44-
val metrics = httpGetMetrics("/metrics")
45+
val metrics = httpGetMetrics("/metrics").content
4546
// assert
4647
metrics shouldBe ""
4748
}
@@ -50,7 +51,7 @@ abstract class EmbeddedHttpServerSpecSuite extends AnyWordSpec
5051
// arrange
5152
testee.reportPeriodSnapshot(counter("jvm.mem"))
5253
// act
53-
val metrics = httpGetMetrics("/metrics")
54+
val metrics = httpGetMetrics("/metrics").content
5455
// assert
5556
metrics shouldBe "# TYPE jvm_mem_total counter\njvm_mem_total 1.0\n"
5657
}
@@ -60,8 +61,9 @@ abstract class EmbeddedHttpServerSpecSuite extends AnyWordSpec
6061
testee.reconfigure(testConfig)
6162
testee.reportPeriodSnapshot(counter("jvm.mem"))
6263
// act
63-
val metrics = httpGetMetrics("/metrics")
64+
val metrics = httpGetMetrics("/metrics").content
6465
// assert
66+
println(metrics)
6567
metrics shouldBe "# TYPE jvm_mem_total counter\njvm_mem_total 2.0\n"
6668
}
6769

@@ -70,42 +72,58 @@ abstract class EmbeddedHttpServerSpecSuite extends AnyWordSpec
7072
testee.reportPeriodSnapshot(counter("jvm.mem"))
7173
// act
7274
val metrics = httpGetMetrics("/metrics")
73-
val gzippedMetrics = httpGetGzippedMetrics("/metrics")
75+
val gzippedMetrics = httpGetMetrics("/metrics", useGzipEncoding = true)
76+
// assert
77+
metrics.contentLength should be > gzippedMetrics.contentLength
78+
}
79+
80+
"property set Content-Type" in {
81+
// arrange
82+
testee.reportPeriodSnapshot(counter("jvm.mem"))
83+
// act
84+
val metrics = httpGetMetrics("/metrics")
85+
val gzippedMetrics = httpGetMetrics("/metrics", useGzipEncoding = true)
7486
// assert
75-
metrics.length should be > gzippedMetrics.length
87+
metrics.headers("Content-type").head shouldBe "text/plain; charset=UTF-8"
88+
gzippedMetrics.headers("Content-type").head shouldBe "text/plain; charset=UTF-8"
7689
}
7790

7891
"respect the path configuration" in {
79-
httpGetMetrics("/metrics") should not be empty
92+
httpGetMetrics("/metrics").content should not be empty
8093
assertThrows[FileNotFoundException] {
8194
httpGetMetrics("/new-metrics")
8295
}
8396

8497
testee.reconfigure(changeEndpoint("/new-metrics"))
85-
httpGetMetrics("/new-metrics") should not be empty
98+
httpGetMetrics("/new-metrics").content should not be empty
8699

87100
assertThrows[FileNotFoundException] {
88-
httpGetMetrics("/metrics")
101+
httpGetMetrics("/metrics").content
89102
}
90103
}
91104
}
92105

93-
private def httpGetMetrics(endpoint: String): String = {
94-
val url = new URL(s"http://127.0.0.1:$port$endpoint")
95-
val src = scala.io.Source.fromURL(url)
96-
try src.mkString
97-
finally src.close()
98-
}
106+
private case class Result(content: String, headers: Map[String, List[String]], contentLength: Int)
99107

100-
private def httpGetGzippedMetrics(endpoint: String): String = {
108+
private def httpGetMetrics(endpoint: String, useGzipEncoding: Boolean = false): Result = {
101109
val url = new URL(s"http://127.0.0.1:$port$endpoint")
102110
val connection = url.openConnection
103-
connection.setRequestProperty("Accept-Encoding", "gzip")
104-
val gzipStream = new GZIPInputStream(connection.getInputStream)
105-
val src = scala.io.Source.fromInputStream(gzipStream)
106-
connection.getRequestProperty("Accept-Encoding") shouldBe "gzip"
107-
try src.getLines.mkString
108-
finally gzipStream.close()
111+
val stream = if (useGzipEncoding) {
112+
connection.setRequestProperty("Accept-Encoding", "gzip")
113+
new GZIPInputStream(connection.getInputStream)
114+
} else connection.getInputStream
115+
val src = scala.io.Source.fromInputStream(stream)
116+
if (useGzipEncoding) {
117+
connection.getRequestProperty("Accept-Encoding") shouldBe "gzip"
118+
}
119+
try {
120+
val content = src.mkString
121+
Result(
122+
content,
123+
connection.getHeaderFields.asScala.toMap.view.mapValues(_.asScala.toList).toMap,
124+
connection.getContentLength
125+
)
126+
} finally stream.close()
109127
}
110128

111129
private def changeEndpoint(path: String): Config = {

0 commit comments

Comments
 (0)