Skip to content

Commit a125fc3

Browse files
authored
Added code to correctly handle HEAD request (#688)
* Added code to correctly handle HEAD request Signed-off-by: Doug Hoard <doug.hoard@gmail.com> * Refactored solution and associated test code Signed-off-by: Doug Hoard <doug.hoard@gmail.com>
1 parent 4451776 commit a125fc3

2 files changed

Lines changed: 58 additions & 25 deletions

File tree

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ public static class HTTPMetricHandler implements HttpHandler {
8383
@Override
8484
public void handle(HttpExchange t) throws IOException {
8585
String query = t.getRequestURI().getRawQuery();
86-
8786
String contextPath = t.getHttpContext().getPath();
8887
ByteArrayOutputStream response = this.response.get();
8988
response.reset();
@@ -114,9 +113,12 @@ public void handle(HttpExchange t) throws IOException {
114113
os.close();
115114
}
116115
} else {
117-
t.getResponseHeaders().set("Content-Length",
118-
String.valueOf(response.size()));
119-
t.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.size());
116+
long contentLength = response.size();
117+
t.getResponseHeaders().set("Content-Length", String.valueOf(contentLength));
118+
if (t.getRequestMethod().equals("HEAD")) {
119+
contentLength = -1;
120+
}
121+
t.sendResponseHeaders(HttpURLConnection.HTTP_OK, contentLength);
120122
response.writeTo(t.getResponseBody());
121123
}
122124
t.close();

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

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.prometheus.client.CollectorRegistry;
88
import java.io.IOException;
99
import java.io.UnsupportedEncodingException;
10+
import java.net.HttpURLConnection;
1011
import java.net.InetSocketAddress;
1112
import java.net.URL;
1213
import java.net.URLConnection;
@@ -34,24 +35,29 @@ public void init() throws IOException {
3435
Gauge.build("c", "a help").register(registry);
3536
}
3637

37-
String request(HTTPServer s, String context, String suffix) throws IOException {
38+
Response request(String requestMethod, HTTPServer s, String context, String suffix) throws IOException {
3839
String url = "http://localhost:" + s.server.getAddress().getPort() + context + suffix;
3940
URLConnection connection = new URL(url).openConnection();
41+
((HttpURLConnection)connection).setRequestMethod(requestMethod);
4042
connection.setDoOutput(true);
4143
connection.connect();
4244
Scanner scanner = new Scanner(connection.getInputStream(), "UTF-8").useDelimiter("\\A");
43-
return scanner.hasNext() ? scanner.next() : "";
45+
return new Response(connection.getContentLength(), scanner.hasNext() ? scanner.next() : "");
4446
}
4547

46-
String request(HTTPServer s, String suffix) throws IOException {
48+
Response request(HTTPServer s, String context, String suffix) throws IOException {
49+
return request("GET", s, context, suffix);
50+
}
51+
52+
Response request(HTTPServer s, String suffix) throws IOException {
4753
return request(s, "/metrics", suffix);
4854
}
4955

50-
String requestWithCompression(HTTPServer s, String suffix) throws IOException {
56+
Response requestWithCompression(HTTPServer s, String suffix) throws IOException {
5157
return requestWithCompression(s, "/metrics", suffix);
5258
}
5359

54-
String requestWithCompression(HTTPServer s, String context, String suffix) throws IOException {
60+
Response requestWithCompression(HTTPServer s, String context, String suffix) throws IOException {
5561
String url = "http://localhost:" + s.server.getAddress().getPort() + context + suffix;
5662
URLConnection connection = new URL(url).openConnection();
5763
connection.setDoOutput(true);
@@ -60,20 +66,20 @@ String requestWithCompression(HTTPServer s, String context, String suffix) throw
6066
connection.connect();
6167
GZIPInputStream gzs = new GZIPInputStream(connection.getInputStream());
6268
Scanner scanner = new Scanner(gzs).useDelimiter("\\A");
63-
return scanner.hasNext() ? scanner.next() : "";
69+
return new Response(connection.getContentLength(), scanner.hasNext() ? scanner.next() : "");
6470
}
6571

66-
String requestWithAccept(HTTPServer s, String accept) throws IOException {
72+
Response requestWithAccept(HTTPServer s, String accept) throws IOException {
6773
String url = "http://localhost:" + s.server.getAddress().getPort();
6874
URLConnection connection = new URL(url).openConnection();
6975
connection.setDoOutput(true);
7076
connection.setDoInput(true);
7177
connection.setRequestProperty("Accept", accept);
7278
Scanner scanner = new Scanner(connection.getInputStream(), "UTF-8").useDelimiter("\\A");
73-
return scanner.hasNext() ? scanner.next() : "";
79+
return new Response(connection.getContentLength(), scanner.hasNext() ? scanner.next() : "");
7480
}
7581

76-
String requestWithCredentials(HTTPServer httpServer, String context, String suffix, String user, String password) throws IOException {
82+
Response requestWithCredentials(HTTPServer httpServer, String context, String suffix, String user, String password) throws IOException {
7783
String url = "http://localhost:" + httpServer.server.getAddress().getPort() + context + suffix;
7884
URLConnection connection = new URL(url).openConnection();
7985
connection.setDoOutput(true);
@@ -82,7 +88,7 @@ String requestWithCredentials(HTTPServer httpServer, String context, String suff
8288
}
8389
connection.connect();
8490
Scanner s = new Scanner(connection.getInputStream(), "UTF-8").useDelimiter("\\A");
85-
return s.hasNext() ? s.next() : "";
91+
return new Response(connection.getContentLength(), s.hasNext() ? s.next() : "");
8692
}
8793

8894
String encodeCredentials(String user, String password) {
@@ -117,7 +123,7 @@ public void testRefuseUsingUnbound() throws IOException {
117123
public void testSimpleRequest() throws IOException {
118124
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
119125
try {
120-
String response = request(s, "");
126+
String response = request(s, "").body;
121127
assertThat(response).contains("a 0.0");
122128
assertThat(response).contains("b 0.0");
123129
assertThat(response).contains("c 0.0");
@@ -130,7 +136,7 @@ public void testSimpleRequest() throws IOException {
130136
public void testBadParams() throws IOException {
131137
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
132138
try {
133-
String response = request(s, "?x");
139+
String response = request(s, "?x").body;
134140
assertThat(response).contains("a 0.0");
135141
assertThat(response).contains("b 0.0");
136142
assertThat(response).contains("c 0.0");
@@ -143,7 +149,7 @@ public void testBadParams() throws IOException {
143149
public void testSingleName() throws IOException {
144150
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
145151
try {
146-
String response = request(s, "?name[]=a");
152+
String response = request(s, "?name[]=a").body;
147153
assertThat(response).contains("a 0.0");
148154
assertThat(response).doesNotContain("b 0.0");
149155
assertThat(response).doesNotContain("c 0.0");
@@ -156,7 +162,7 @@ public void testSingleName() throws IOException {
156162
public void testMultiName() throws IOException {
157163
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
158164
try {
159-
String response = request(s, "?name[]=a&name[]=b");
165+
String response = request(s, "?name[]=a&name[]=b").body;
160166
assertThat(response).contains("a 0.0");
161167
assertThat(response).contains("b 0.0");
162168
assertThat(response).doesNotContain("c 0.0");
@@ -174,7 +180,7 @@ public void testSampleNameFilter() throws IOException {
174180
.build())
175181
.build();
176182
try {
177-
String response = request(s, "?name[]=a&name[]=b");
183+
String response = request(s, "?name[]=a&name[]=b").body;
178184
assertThat(response).doesNotContain("a 0.0");
179185
assertThat(response).contains("b 0.0");
180186
assertThat(response).doesNotContain("c 0.0");
@@ -187,7 +193,7 @@ public void testSampleNameFilter() throws IOException {
187193
public void testDecoding() throws IOException {
188194
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
189195
try {
190-
String response = request(s, "?n%61me[]=%61");
196+
String response = request(s, "?n%61me[]=%61").body;
191197
assertThat(response).contains("a 0.0");
192198
assertThat(response).doesNotContain("b 0.0");
193199
assertThat(response).doesNotContain("c 0.0");
@@ -200,7 +206,7 @@ public void testDecoding() throws IOException {
200206
public void testGzipCompression() throws IOException {
201207
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
202208
try {
203-
String response = requestWithCompression(s, "");
209+
String response = requestWithCompression(s, "").body;
204210
assertThat(response).contains("a 0.0");
205211
assertThat(response).contains("b 0.0");
206212
assertThat(response).contains("c 0.0");
@@ -213,7 +219,7 @@ public void testGzipCompression() throws IOException {
213219
public void testOpenMetrics() throws IOException {
214220
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
215221
try {
216-
String response = requestWithAccept(s, "application/openmetrics-text; version=0.0.1,text/plain;version=0.0.4;q=0.5,*/*;q=0.1");
222+
String response = requestWithAccept(s, "application/openmetrics-text; version=0.0.1,text/plain;version=0.0.4;q=0.5,*/*;q=0.1").body;
217223
assertThat(response).contains("# EOF");
218224
} finally {
219225
s.close();
@@ -224,7 +230,7 @@ public void testOpenMetrics() throws IOException {
224230
public void testHealth() throws IOException {
225231
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
226232
try {
227-
String response = request(s, "/-/healthy", "");
233+
String response = request(s, "/-/healthy", "").body;
228234
assertThat(response).contains("Exporter is Healthy");
229235
} finally {
230236
s.close();
@@ -235,7 +241,7 @@ public void testHealth() throws IOException {
235241
public void testHealthGzipCompression() throws IOException {
236242
HTTPServer s = new HTTPServer(new InetSocketAddress(0), registry);
237243
try {
238-
String response = requestWithCompression(s, "/-/healthy", "");
244+
String response = requestWithCompression(s, "/-/healthy", "").body;
239245
assertThat(response).contains("Exporter is Healthy");
240246
} finally {
241247
s.close();
@@ -249,7 +255,7 @@ public void testBasicAuthSuccess() throws IOException {
249255
.withAuthenticator(createAuthenticator("/", "user", "secret"))
250256
.build();
251257
try {
252-
String response = requestWithCredentials(s, "/metrics","?name[]=a&name[]=b", "user", "secret");
258+
String response = requestWithCredentials(s, "/metrics","?name[]=a&name[]=b", "user", "secret").body;
253259
assertThat(response).contains("a 0.0");
254260
} finally {
255261
s.close();
@@ -287,4 +293,29 @@ public void testBasicAuthWrongCredentials() throws IOException {
287293
s.close();
288294
}
289295
}
296+
297+
@Test
298+
public void testHEADRequest() throws IOException {
299+
HTTPServer s = new HTTPServer.Builder()
300+
.withRegistry(registry)
301+
.build();
302+
try {
303+
Response response = request("HEAD", s, "/metrics", "?name[]=a&name[]=b");
304+
Assert.assertTrue(response.contentLength == 74);
305+
Assert.assertTrue("".equals(response.body));
306+
} finally {
307+
s.close();
308+
}
309+
}
310+
311+
class Response {
312+
313+
public long contentLength;
314+
public String body;
315+
316+
public Response(long contentLength, String body) {
317+
this.contentLength = contentLength;
318+
this.body = body;
319+
}
320+
}
290321
}

0 commit comments

Comments
 (0)