diff --git a/pom.xml b/pom.xml
index 09c42666a..91dde9aae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -168,6 +168,26 @@
+
+ pl.project13.maven
+ git-commit-id-plugin
+ 5.0.0
+
+
+
+ revision
+
+
+
+
+ true
+ ${project.build.outputDirectory}/git.properties
+
+ git.commit.id.abbrev
+ git.commit.id
+
+
+
org.apache.maven.plugins
maven-javadoc-plugin
diff --git a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java
index 233325750..02000e85e 100644
--- a/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java
+++ b/src/main/java/org/gaul/s3proxy/S3ProxyHandler.java
@@ -41,6 +41,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.TimeZone;
@@ -58,6 +59,7 @@
import javax.xml.stream.XMLStreamWriter;
import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
@@ -293,6 +295,13 @@ public final void doHandle(HttpServletRequest baseRequest,
String uri = request.getRequestURI();
String originalUri = request.getRequestURI();
+ String healthzUri = servicePath.isEmpty() ? "/healthz" :
+ servicePath + "/healthz";
+ if (healthzUri.equals(uri) && "GET".equalsIgnoreCase(method)) {
+ handleStatuszRequest(response);
+ return;
+ }
+
if (!this.servicePath.isEmpty()) {
if (uri.length() > this.servicePath.length()) {
uri = uri.substring(this.servicePath.length());
@@ -2030,6 +2039,55 @@ private void handlePutBlob(HttpServletRequest request,
response.addHeader(HttpHeaders.ETAG, maybeQuoteETag(eTag));
}
+ private void handleStatuszRequest(HttpServletResponse response)
+ throws IOException {
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("application/json");
+ response.setCharacterEncoding(UTF_8);
+
+ var statusBody = ImmutableMap.of("gitHash", StatusMetadata.INSTANCE.gitHash);
+ String versionInfo = StatusMetadata.JSON_MAPPER.writeValueAsString(statusBody);
+
+ try (PrintWriter writer = response.getWriter()) {
+ writer.write(versionInfo);
+ writer.flush();
+ }
+ }
+
+ private static final class StatusMetadata {
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+ private static final StatusMetadata INSTANCE = StatusMetadata.load();
+ private static final String UNKNOWN_VALUE = "unknown";
+ private final String gitHash;
+
+ private StatusMetadata(String gitHash) {
+ this.gitHash = gitHash;
+ }
+
+ static StatusMetadata load() {
+ String gitHash = loadGitHash();
+ return new StatusMetadata(gitHash);
+ }
+
+ private static String loadGitHash() {
+ try (InputStream stream = S3ProxyHandler.class.getClassLoader()
+ .getResourceAsStream("git.properties")) {
+ if (stream == null) {
+ return UNKNOWN_VALUE;
+ }
+ Properties properties = new Properties();
+ properties.load(stream);
+ return Optional.ofNullable(
+ properties.getProperty("git.commit.id.abbrev"))
+ .orElseGet(() -> properties.getProperty("git.commit.id",
+ UNKNOWN_VALUE));
+ } catch (IOException ioe) {
+ logger.debug("Unable to load git.properties", ioe);
+ return UNKNOWN_VALUE;
+ }
+ }
+ }
+
private void handlePostBlob(HttpServletRequest request,
HttpServletResponse response, InputStream is, BlobStore blobStore,
String containerName)
diff --git a/src/test/java/org/gaul/s3proxy/AwsSdkAnonymousTest.java b/src/test/java/org/gaul/s3proxy/AwsSdkAnonymousTest.java
index ad260ca3e..d65f1ced4 100644
--- a/src/test/java/org/gaul/s3proxy/AwsSdkAnonymousTest.java
+++ b/src/test/java/org/gaul/s3proxy/AwsSdkAnonymousTest.java
@@ -19,7 +19,9 @@
import static org.assertj.core.api.Assertions.assertThat;
import java.io.InputStream;
+import java.net.HttpURLConnection;
import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.util.Random;
import com.amazonaws.SDKGlobalConfiguration;
@@ -50,6 +52,7 @@ public final class AwsSdkAnonymousTest {
private static final ByteSource BYTE_SOURCE = ByteSource.wrap(new byte[1]);
private URI s3Endpoint;
+ private URI httpEndpoint;
private EndpointConfiguration s3EndpointConfig;
private S3Proxy s3Proxy;
private BlobStoreContext context;
@@ -66,6 +69,7 @@ public void setUp() throws Exception {
awsCreds = new AnonymousAWSCredentials();
context = info.getBlobStore().getContext();
s3Proxy = info.getS3Proxy();
+ httpEndpoint = info.getEndpoint();
s3Endpoint = info.getSecureEndpoint();
servicePath = info.getServicePath();
s3EndpointConfig = new EndpointConfiguration(
@@ -128,6 +132,31 @@ public void testAwsV4SignatureChunkedAnonymous() throws Exception {
}
}
+ @Test
+ public void testHealthzEndpoint() throws Exception {
+ URI baseUri = httpEndpoint != null ? httpEndpoint : s3Endpoint;
+ String path = (servicePath == null ? "" : servicePath) + "/healthz";
+ URI healthzUri = new URI(baseUri.getScheme(), baseUri.getUserInfo(),
+ baseUri.getHost(), baseUri.getPort(), path,
+ baseUri.getQuery(), baseUri.getFragment());
+
+ HttpURLConnection connection =
+ (HttpURLConnection) healthzUri.toURL().openConnection();
+ connection.setRequestMethod("GET");
+
+ assertThat(connection.getResponseCode()).isEqualTo(200);
+
+ String body;
+ try (InputStream stream = connection.getInputStream()) {
+ body = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
+ } finally {
+ connection.disconnect();
+ }
+
+ assertThat(body).contains("\"gitHash\":\"");
+ assertThat(body).startsWith("{").endsWith("}");
+ }
+
private static String createRandomContainerName() {
return "s3proxy-" + new Random().nextInt(Integer.MAX_VALUE);
}