diff --git a/http-client-core/src/main/java/io/micronaut/http/client/interceptor/HttpClientIntroductionAdvice.java b/http-client-core/src/main/java/io/micronaut/http/client/interceptor/HttpClientIntroductionAdvice.java index 24ccc2f94c6..6d400b58a7e 100644 --- a/http-client-core/src/main/java/io/micronaut/http/client/interceptor/HttpClientIntroductionAdvice.java +++ b/http-client-core/src/main/java/io/micronaut/http/client/interceptor/HttpClientIntroductionAdvice.java @@ -299,11 +299,8 @@ public Object intercept(MethodInvocationContext context) { request.setAttribute(HttpAttributes.INVOCATION_CONTEXT, context); // Set the URI template used to make the request for tracing purposes request.setAttribute(HttpAttributes.URI_TEMPLATE, resolveTemplate(annotationMetadata, uriTemplate.toString())); - String serviceId = getClientId(annotationMetadata); Argument errorType = annotationMetadata.classValue(Client.class, "errorType") .map((Function) Argument::of).orElse(HttpClient.DEFAULT_ERROR_TYPE); - request.setAttribute(HttpAttributes.SERVICE_ID, serviceId); - final MediaType[] acceptTypes; Collection accept = request.accept(); diff --git a/http-client/src/main/java/io/micronaut/http/client/netty/DefaultHttpClient.java b/http-client/src/main/java/io/micronaut/http/client/netty/DefaultHttpClient.java index c79922938a7..33ad3612006 100644 --- a/http-client/src/main/java/io/micronaut/http/client/netty/DefaultHttpClient.java +++ b/http-client/src/main/java/io/micronaut/http/client/netty/DefaultHttpClient.java @@ -35,6 +35,7 @@ import io.micronaut.core.util.CollectionUtils; import io.micronaut.core.util.StringUtils; import io.micronaut.core.util.SupplierUtil; +import io.micronaut.http.HttpAttributes; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpResponseWrapper; import io.micronaut.http.HttpStatus; @@ -1188,7 +1189,13 @@ private > Publisher applyFi Publisher responsePublisher) { if (request instanceof MutableHttpRequest) { - ((MutableHttpRequest) request).uri(requestURI); + MutableHttpRequest mutRequest = (MutableHttpRequest) request; + mutRequest.uri(requestURI); + if (informationalServiceId != null && + !mutRequest.getAttribute(HttpAttributes.SERVICE_ID).isPresent()) { + + mutRequest.setAttribute(HttpAttributes.SERVICE_ID, informationalServiceId); + } List filters = filterResolver.resolveFilters(request, clientFilterEntries); diff --git a/http-client/src/test/groovy/io/micronaut/http/client/ServiceIdSpec.groovy b/http-client/src/test/groovy/io/micronaut/http/client/ServiceIdSpec.groovy new file mode 100644 index 00000000000..3efb8c7a022 --- /dev/null +++ b/http-client/src/test/groovy/io/micronaut/http/client/ServiceIdSpec.groovy @@ -0,0 +1,101 @@ +package io.micronaut.http.client + +import io.micronaut.context.ApplicationContext +import io.micronaut.context.annotation.Requires +import io.micronaut.http.HttpAttributes +import io.micronaut.http.HttpRequest +import io.micronaut.http.HttpResponse +import io.micronaut.http.HttpVersion +import io.micronaut.http.MutableHttpRequest +import io.micronaut.http.annotation.Controller +import io.micronaut.http.annotation.Filter +import io.micronaut.http.annotation.Get +import io.micronaut.http.client.annotation.Client +import io.micronaut.http.filter.ClientFilterChain +import io.micronaut.http.filter.HttpClientFilter +import io.micronaut.runtime.server.EmbeddedServer +import jakarta.inject.Singleton +import org.reactivestreams.Publisher +import spock.lang.Specification + +class ServiceIdSpec extends Specification { + + def 'service id set by declarative client'() { + given: + def serverCtx = ApplicationContext.run([ + 'spec.name': 'ServiceIdSpec', + ]) + def server = serverCtx.getBean(EmbeddedServer) + server.start() + def clientCtx = ApplicationContext.run([ + 'spec.name': 'ServiceIdSpec', + 'micronaut.http.services.my-client-id.url': server.URI, + ]) + def client = clientCtx.getBean(DeclarativeClient) + def filter = clientCtx.getBean(ServiceIdFilter) + + expect: + filter.serviceId == null + client.index() == "foo" + filter.serviceId == "my-client-id" + + cleanup: + server.close() + serverCtx.close() + clientCtx.close() + } + + def 'service id set by normal client'() { + given: + def serverCtx = ApplicationContext.run([ + 'spec.name': 'ServiceIdSpec', + ]) + def server = serverCtx.getBean(EmbeddedServer) + server.start() + def clientCtx = ApplicationContext.run([ + 'spec.name': 'ServiceIdSpec', + 'micronaut.http.services.my-client-id.url': server.URI, + ]) + def client = clientCtx.getBean(HttpClientRegistry).getClient(HttpVersion.HTTP_1_1, "my-client-id", null) + def filter = clientCtx.getBean(ServiceIdFilter) + + expect: + filter.serviceId == null + client.toBlocking().exchange("/service-id", String).body() == "foo" + filter.serviceId == "my-client-id" + + cleanup: + server.close() + serverCtx.close() + clientCtx.close() + } + + @Client(id = "my-client-id") + static interface DeclarativeClient { + @Get("/service-id") + String index() + } + + @Singleton + @Requires(property = "spec.name", value = "ServiceIdSpec") + @Controller("/service-id") + static class ServiceIdController { + @Get + def index(HttpRequest request) { + return "foo" + } + } + + @Singleton + @Requires(property = "spec.name", value = "ServiceIdSpec") + @Filter(Filter.MATCH_ALL_PATTERN) + static class ServiceIdFilter implements HttpClientFilter { + String serviceId + + @Override + Publisher> doFilter(MutableHttpRequest request, ClientFilterChain chain) { + serviceId = request.getAttribute(HttpAttributes.SERVICE_ID).orElse(null) + return chain.proceed(request) + } + } +}