Skip to content

Commit f195003

Browse files
erebebrian-brazil
authored andcommitted
HTTP Server: Add support for Gzip Compression + Reuse ByteArray (prometheus#291)
1 parent 5a00651 commit f195003

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

simpleclient_httpserver/src/main/java/io/prometheus/client/exporter/HTTPServer.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
import java.io.ByteArrayOutputStream;
77
import java.io.IOException;
88
import java.io.OutputStreamWriter;
9+
import java.net.HttpURLConnection;
910
import java.net.InetSocketAddress;
1011
import java.net.URLDecoder;
12+
import java.util.List;
1113
import java.util.Set;
1214
import java.util.HashSet;
1315
import java.util.concurrent.Executors;
16+
import java.util.zip.GZIPOutputStream;
1417

1518
import com.sun.net.httpserver.HttpHandler;
1619
import com.sun.net.httpserver.HttpServer;
@@ -27,8 +30,16 @@
2730
* </pre>
2831
* */
2932
public class HTTPServer {
33+
private static class LocalByteArray extends ThreadLocal<ByteArrayOutputStream> {
34+
protected ByteArrayOutputStream initialValue()
35+
{
36+
return new ByteArrayOutputStream(1 << 20);
37+
}
38+
}
39+
3040
static class HTTPMetricHandler implements HttpHandler {
3141
private CollectorRegistry registry;
42+
private final LocalByteArray response = new LocalByteArray();
3243

3344
HTTPMetricHandler(CollectorRegistry registry) {
3445
this.registry = registry;
@@ -38,7 +49,8 @@ static class HTTPMetricHandler implements HttpHandler {
3849
public void handle(HttpExchange t) throws IOException {
3950
String query = t.getRequestURI().getRawQuery();
4051

41-
ByteArrayOutputStream response = new ByteArrayOutputStream(1 << 20);
52+
ByteArrayOutputStream response = this.response.get();
53+
response.reset();
4254
OutputStreamWriter osw = new OutputStreamWriter(response);
4355
TextFormat.write004(osw,
4456
registry.filteredMetricFamilySamples(parseQuery(query)));
@@ -51,13 +63,36 @@ public void handle(HttpExchange t) throws IOException {
5163
TextFormat.CONTENT_TYPE_004);
5264
t.getResponseHeaders().set("Content-Length",
5365
String.valueOf(response.size()));
54-
t.sendResponseHeaders(200, response.size());
55-
response.writeTo(t.getResponseBody());
66+
if (shouldUseCompression(t)) {
67+
t.getResponseHeaders().set("Content-Encoding", "gzip");
68+
t.sendResponseHeaders(HttpURLConnection.HTTP_OK, 0);
69+
final GZIPOutputStream os = new GZIPOutputStream(t.getResponseBody());
70+
response.writeTo(os);
71+
os.finish();
72+
} else {
73+
t.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.size());
74+
response.writeTo(t.getResponseBody());
75+
}
5676
t.close();
5777
}
5878

5979
}
6080

81+
protected static boolean shouldUseCompression(HttpExchange exchange) {
82+
List<String> encodingHeaders = exchange.getRequestHeaders().get("Accept-Encoding");
83+
if (encodingHeaders == null) return false;
84+
85+
for (String encodingHeader : encodingHeaders) {
86+
String[] encodings = encodingHeader.split(",");
87+
for (String encoding : encodings) {
88+
if (encoding.trim().toLowerCase().equals("gzip")) {
89+
return true;
90+
}
91+
}
92+
}
93+
return false;
94+
}
95+
6196
protected static Set<String> parseQuery(String query) throws IOException {
6297
Set<String> names = new HashSet<String>();
6398
if (query != null) {

simpleclient_httpserver/src/test/java/io/prometheus/client/exporter/TestHTTPServer.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.net.URL;
88
import java.net.URLConnection;
99
import java.util.Scanner;
10+
import java.util.zip.GZIPInputStream;
11+
1012
import org.junit.After;
1113
import org.junit.Before;
1214
import org.junit.Test;
@@ -40,6 +42,18 @@ String request(String suffix) throws IOException {
4042
return s.hasNext() ? s.next() : "";
4143
}
4244

45+
String requestWithCompression(String suffix) throws IOException {
46+
String url = "http://localhost:" + s.server.getAddress().getPort() + "/metrics" + suffix;
47+
URLConnection connection = new URL(url).openConnection();
48+
connection.setDoOutput(true);
49+
connection.setDoInput(true);
50+
connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
51+
connection.connect();
52+
GZIPInputStream gzs = new GZIPInputStream(connection.getInputStream());
53+
Scanner s = new Scanner(gzs).useDelimiter("\\A");
54+
return s.hasNext() ? s.next() : "";
55+
}
56+
4357
@Test
4458
public void testSimpleRequest() throws IOException {
4559
String response = request("");
@@ -80,4 +94,11 @@ public void testDecoding() throws IOException {
8094
assertThat(response).doesNotContain("c 0.0");
8195
}
8296

97+
@Test
98+
public void testGzipCompression() throws IOException {
99+
String response = requestWithCompression("");
100+
assertThat(response).contains("a 0.0");
101+
assertThat(response).contains("b 0.0");
102+
assertThat(response).contains("c 0.0");
103+
}
83104
}

0 commit comments

Comments
 (0)