3232import java .util .LinkedHashSet ;
3333import java .util .List ;
3434import java .util .Locale ;
35+ import java .util .Map ;
36+ import java .util .Objects ;
3537import java .util .Set ;
3638import java .util .Vector ;
3739import java .util .function .Function ;
5052import org .springframework .core .Conventions ;
5153import org .springframework .core .MethodParameter ;
5254import org .springframework .core .ParameterizedTypeReference ;
55+ import org .springframework .http .HttpEntity ;
5356import org .springframework .http .HttpHeaders ;
5457import org .springframework .http .RequestEntity ;
5558import org .springframework .http .RequestEntity .BodyBuilder ;
@@ -147,6 +150,10 @@ public class ProxyExchange<T> {
147150
148151 private URI uri ;
149152
153+ private String uriTemplate ;
154+
155+ private Map <String , ?> uriVariables ;
156+
150157 private RestTemplate rest ;
151158
152159 private Object body ;
@@ -247,6 +254,8 @@ public ProxyExchange<T> excluded(String... names) {
247254 */
248255 public ProxyExchange <T > uri (URI uri ) {
249256 this .uri = uri ;
257+ this .uriTemplate = null ;
258+ this .uriVariables = null ;
250259 return this ;
251260 }
252261
@@ -264,6 +273,21 @@ public ProxyExchange<T> uri(String uri) {
264273 }
265274 }
266275
276+ /**
277+ * Sets the uri for the backend call using a URI template with variables. When a
278+ * template is provided, the downstream {@link RestTemplate} call preserves the
279+ * template pattern for observability (e.g. Micrometer URI tags).
280+ * @param uriTemplate the URI template (e.g. {@code "http://service/foos/{id}"})
281+ * @param uriVariables the variables to expand in the template
282+ * @return this for convenience
283+ */
284+ public ProxyExchange <T > uri (String uriTemplate , Map <String , ?> uriVariables ) {
285+ this .uriTemplate = uriTemplate ;
286+ this .uriVariables = uriVariables ;
287+ this .uri = rest .getUriTemplateHandler ().expand (uriTemplate , uriVariables );
288+ return this ;
289+ }
290+
267291 public String path () {
268292 return (String ) this .webRequest .getAttribute (HandlerMapping .PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE ,
269293 WebRequest .SCOPE_REQUEST );
@@ -357,6 +381,11 @@ private ResponseEntity<T> exchange(RequestEntity<?> requestEntity) {
357381 if (type instanceof TypeVariable || type instanceof WildcardType ) {
358382 type = Object .class ;
359383 }
384+ if (this .uriTemplate != null && this .uriVariables != null ) {
385+ return rest .exchange (this .uriTemplate , Objects .requireNonNull (requestEntity .getMethod ()),
386+ new HttpEntity <>(requestEntity .getBody (), requestEntity .getHeaders ()),
387+ ParameterizedTypeReference .forType (type ), this .uriVariables );
388+ }
360389 return rest .exchange (requestEntity , ParameterizedTypeReference .forType (type ));
361390 }
362391
0 commit comments