diff --git a/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivity.java b/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivity.java index abc23a53a3e..3db3f715743 100644 --- a/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivity.java +++ b/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivity.java @@ -146,7 +146,7 @@ public CompletableFuture notifyClientTerminatio try { String clientId = ctx.getClientID(); - LanguageCode languageCode = LanguageCode.valueOf(ctx.getLanguage()); + LanguageCode languageCode = parseLanguage(ctx); Settings clientSettings = grpcClientSettingsManager.removeAndGetClientSettings(ctx); if (clientSettings == null) { future.complete(NotifyClientTerminationResponse.newBuilder() @@ -415,7 +415,7 @@ protected TelemetryCommand processClientSettings(ProxyContext ctx, TelemetryComm protected GrpcClientChannel registerProducer(ProxyContext ctx, String topicName) { String clientId = ctx.getClientID(); - LanguageCode languageCode = LanguageCode.valueOf(ctx.getLanguage()); + LanguageCode languageCode = parseLanguage(ctx); GrpcClientChannel channel = this.grpcChannelManager.createChannel(ctx, clientId); // use topic name as producer group @@ -431,7 +431,7 @@ protected GrpcClientChannel registerProducer(ProxyContext ctx, String topicName) protected GrpcClientChannel registerConsumer(ProxyContext ctx, String consumerGroup, ClientType clientType, List subscriptionEntryList, boolean updateSubscription) { String clientId = ctx.getClientID(); - LanguageCode languageCode = LanguageCode.valueOf(ctx.getLanguage()); + LanguageCode languageCode = parseLanguage(ctx); GrpcClientChannel channel = this.grpcChannelManager.createChannel(ctx, clientId); ClientChannelInfo clientChannelInfo = new ClientChannelInfo(channel, clientId, languageCode, parseClientVersion(ctx.getClientVersion())); @@ -461,6 +461,18 @@ private int parseClientVersion(String clientVersionStr) { return clientVersion; } + private LanguageCode parseLanguage(ProxyContext ctx) { + String language = ctx.getLanguage(); + if (StringUtils.isBlank(language)) { + throw new GrpcProxyException(Code.BAD_REQUEST, "language cannot be empty"); + } + try { + return LanguageCode.valueOf(language); + } catch (IllegalArgumentException e) { + throw new GrpcProxyException(Code.BAD_REQUEST, "unsupported language: " + language, e); + } + } + protected void reportThreadStackTrace(ProxyContext ctx, Status status, ThreadStackTrace request) { String nonce = request.getNonce(); String threadStack = request.getThreadStackTrace(); diff --git a/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivityTest.java b/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivityTest.java index e215c6efaba..11c7bc4891e 100644 --- a/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivityTest.java +++ b/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/client/ClientActivityTest.java @@ -325,6 +325,44 @@ public void testErrorProducerConfig() throws Throwable { } } + @Test + public void testInvalidLanguageIsReportedAsInvalidArgument() throws Throwable { + ProxyContext context = createContext().setLanguage("UNKNOWN_LANGUAGE"); + try { + this.sendClientTelemetry( + context, + Settings.newBuilder() + .setClientType(ClientType.PRODUCER) + .setPublishing(Publishing.newBuilder() + .addTopics(Resource.newBuilder().setName(TOPIC).build()) + .build()) + .build()).get(); + fail(); + } catch (ExecutionException e) { + StatusRuntimeException exception = (StatusRuntimeException) e.getCause(); + assertEquals(Status.Code.INVALID_ARGUMENT, exception.getStatus().getCode()); + } + } + + @Test + public void testBlankLanguageIsReportedAsInvalidArgument() throws Throwable { + ProxyContext context = createContext().setLanguage(""); + try { + this.sendClientTelemetry( + context, + Settings.newBuilder() + .setClientType(ClientType.PRODUCER) + .setPublishing(Publishing.newBuilder() + .addTopics(Resource.newBuilder().setName(TOPIC).build()) + .build()) + .build()).get(); + fail(); + } catch (ExecutionException e) { + StatusRuntimeException exception = (StatusRuntimeException) e.getCause(); + assertEquals(Status.Code.INVALID_ARGUMENT, exception.getStatus().getCode()); + } + } + @Test public void testEmptySettings() throws Throwable { ProxyContext context = createContext();