From 18538d65629bdf53fffc798f07b0b140d7fbcac8 Mon Sep 17 00:00:00 2001 From: Francesco Guardiani Date: Thu, 18 Apr 2024 08:44:41 +0200 Subject: [PATCH] Add x-restate-server header in responses. (#285) --- build.gradle.kts | 2 +- sdk-common/build.gradle.kts | 64 +++++++++++++++++++ sdk-core/build.gradle.kts | 2 - .../http/vertx/RequestHttpServerHandler.java | 9 ++- .../sdk/lambda/RestateLambdaEndpoint.java | 5 +- 5 files changed, 76 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6b8ab5f5..4f7110e2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,7 @@ allprojects { configure { java { - targetExclude("build/generated/**/*.java") + targetExclude("build/**/*.java") googleJavaFormat() diff --git a/sdk-common/build.gradle.kts b/sdk-common/build.gradle.kts index 3f0a93d2..65f94437 100644 --- a/sdk-common/build.gradle.kts +++ b/sdk-common/build.gradle.kts @@ -16,3 +16,67 @@ dependencies { testImplementation(testingLibs.junit.jupiter) testImplementation(testingLibs.assertj) } + +val generatedVersionDir = layout.buildDirectory.dir("version") + +generatedVersionDir.get().asFile.mkdirs() + +sourceSets { main { java { srcDir(generatedVersionDir) } } } + +// Configure generation of version class + +// From https://discuss.kotlinlang.org/t/use-git-hash-as-version-number-in-build-gradle-kts/19818/4 +fun String.runCommand( + workingDir: File = File("."), + timeoutAmount: Long = 5, + timeoutUnit: TimeUnit = TimeUnit.SECONDS +): String = + ProcessBuilder(split("\\s(?=(?:[^'\"`]*(['\"`])[^'\"`]*\\1)*[^'\"`]*$)".toRegex())) + .directory(workingDir) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + .start() + .apply { waitFor(timeoutAmount, timeoutUnit) } + .run { + val error = errorStream.bufferedReader().readText().trim() + if (error.isNotEmpty()) { + throw IllegalStateException(error) + } + inputStream.bufferedReader().readText().trim() + } + +val generateVersionClass = + tasks.register("generateVersionClass") { + dependsOn(project.tasks.processResources) + outputs.dir(generatedVersionDir) + + doFirst { + val gitHash = "git rev-parse --short=8 HEAD".runCommand(workingDir = rootDir) + val containingDir = generatedVersionDir.get().dir("dev/restate/sdk/version").asFile + assert(containingDir.exists() || containingDir.mkdirs()) + + file("$containingDir/Version.java") + .writeText( + """ + package dev.restate.sdk.version; + + public final class Version { + private Version() {} + + public static final String VERSION = "$version"; + public static final String GIT_HASH = "$gitHash"; + public static final String X_RESTATE_SERVER = "restate-sdk-java/" + VERSION + "_" + GIT_HASH; + } + """ + .trimIndent()) + + check(file("${projectDir}/build/version/dev/restate/sdk/version/Version.java").exists()) { + "${projectDir}/build/version/dev/restate/sdk/version/Version.java doesn't exist?!" + } + } + } + +tasks { + withType().configureEach { dependsOn(generateVersionClass) } + withType().configureEach { dependsOn(generateVersionClass) } +} diff --git a/sdk-core/build.gradle.kts b/sdk-core/build.gradle.kts index 46dc1853..6879f459 100644 --- a/sdk-core/build.gradle.kts +++ b/sdk-core/build.gradle.kts @@ -1,5 +1,3 @@ -import com.google.protobuf.gradle.id - plugins { `java-library` `library-publishing-conventions` diff --git a/sdk-http-vertx/src/main/java/dev/restate/sdk/http/vertx/RequestHttpServerHandler.java b/sdk-http-vertx/src/main/java/dev/restate/sdk/http/vertx/RequestHttpServerHandler.java index b3e65464..c2e52431 100644 --- a/sdk-http-vertx/src/main/java/dev/restate/sdk/http/vertx/RequestHttpServerHandler.java +++ b/sdk-http-vertx/src/main/java/dev/restate/sdk/http/vertx/RequestHttpServerHandler.java @@ -18,6 +18,7 @@ import dev.restate.sdk.core.ResolvedEndpointHandler; import dev.restate.sdk.core.RestateEndpoint; import dev.restate.sdk.core.manifest.DeploymentManifestSchema; +import dev.restate.sdk.version.Version; import io.netty.util.AsciiString; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.propagation.TextMapGetter; @@ -41,6 +42,9 @@ class RequestHttpServerHandler implements Handler { private static final Logger LOG = LogManager.getLogger(RequestHttpServerHandler.class); private static final AsciiString APPLICATION_RESTATE = AsciiString.cached("application/restate"); + private static final AsciiString X_RESTATE_SERVER_KEY = AsciiString.cached("x-restate-server"); + private static final AsciiString X_RESTATE_SERVER_VALUE = + AsciiString.cached(Version.X_RESTATE_SERVER); private static final ObjectMapper MANIFEST_OBJECT_MAPPER = new ObjectMapper(); private static final Pattern SLASH = Pattern.compile(Pattern.quote("/")); @@ -127,7 +131,9 @@ public void handle(HttpServerRequest request) { // Vert.x will send them as soon as we send the first write HttpServerResponse response = request.response(); response.setStatusCode(OK.code()); - response.putHeader(CONTENT_TYPE, APPLICATION_RESTATE); + response + .putHeader(CONTENT_TYPE, APPLICATION_RESTATE) + .putHeader(X_RESTATE_SERVER_KEY, X_RESTATE_SERVER_VALUE); // This is No-op for HTTP2 response.setChunked(true); @@ -159,6 +165,7 @@ private void handleDiscoveryRequest(HttpServerRequest request) { request .response() .setStatusCode(OK.code()) + .putHeader(X_RESTATE_SERVER_KEY, X_RESTATE_SERVER_VALUE) .putHeader(CONTENT_TYPE, APPLICATION_JSON) .end(responseBuffer); } diff --git a/sdk-lambda/src/main/java/dev/restate/sdk/lambda/RestateLambdaEndpoint.java b/sdk-lambda/src/main/java/dev/restate/sdk/lambda/RestateLambdaEndpoint.java index 11a09f3e..f2f689b5 100644 --- a/sdk-lambda/src/main/java/dev/restate/sdk/lambda/RestateLambdaEndpoint.java +++ b/sdk-lambda/src/main/java/dev/restate/sdk/lambda/RestateLambdaEndpoint.java @@ -19,6 +19,7 @@ import dev.restate.sdk.core.ResolvedEndpointHandler; import dev.restate.sdk.core.RestateEndpoint; import dev.restate.sdk.core.manifest.DeploymentManifestSchema; +import dev.restate.sdk.version.Version; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.context.propagation.TextMapGetter; import java.nio.ByteBuffer; @@ -39,9 +40,9 @@ public final class RestateLambdaEndpoint { private static final String INVOKE_PATH_SEGMENT = "invoke"; private static final String DISCOVER_PATH = "/discover"; private static final Map INVOKE_RESPONSE_HEADERS = - Map.of("content-type", "application/restate"); + Map.of("content-type", "application/restate", "x-restate-server", Version.X_RESTATE_SERVER); private static final Map DISCOVER_RESPONSE_HEADERS = - Map.of("content-type", "application/json"); + Map.of("content-type", "application/json", "x-restate-server", Version.X_RESTATE_SERVER); private static TextMapGetter> OTEL_HEADERS_GETTER = new TextMapGetter<>() {