Skip to content

Commit c8adda7

Browse files
committed
WebClientEurekaHttpClient - Encode special characters; fixes spring-cloudgh-4121
1 parent 044e179 commit c8adda7

File tree

1 file changed

+34
-32
lines changed

1 file changed

+34
-32
lines changed

spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClient.java

+34-32
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.cloud.netflix.eureka.http;
1818

1919
import java.util.Map;
20+
import java.util.Optional;
2021

2122
import com.netflix.appinfo.InstanceInfo;
2223
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
@@ -53,28 +54,28 @@ public WebClientEurekaHttpClient(WebClient webClient) {
5354

5455
@Override
5556
public EurekaHttpResponse<Void> register(InstanceInfo info) {
56-
return webClient.post().uri("apps/" + info.getAppName()).body(BodyInserters.fromValue(info))
57-
.header(HttpHeaders.ACCEPT_ENCODING, "gzip")
57+
return webClient.post().uri(uriBuilder -> uriBuilder.path("apps/{appName}").build(info.getAppName()))
58+
.body(BodyInserters.fromValue(info)).header(HttpHeaders.ACCEPT_ENCODING, "gzip")
5859
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).retrieve()
5960
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
6061
.block();
6162
}
6263

6364
@Override
6465
public EurekaHttpResponse<Void> cancel(String appName, String id) {
65-
return webClient.delete().uri("apps/" + appName + '/' + id).retrieve()
66-
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
67-
.block();
66+
return webClient.delete().uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}").build(appName, id))
67+
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
68+
.map(this::eurekaHttpResponse).block();
6869
}
6970

7071
@Override
7172
public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, InstanceInfo info,
7273
InstanceStatus overriddenStatus) {
73-
String urlPath = "apps/" + appName + '/' + id + "?status=" + info.getStatus().toString()
74-
+ "&lastDirtyTimestamp=" + info.getLastDirtyTimestamp().toString()
75-
+ (overriddenStatus != null ? "&overriddenstatus=" + overriddenStatus.name() : "");
7674

77-
ResponseEntity<InstanceInfo> response = webClient.put().uri(urlPath)
75+
ResponseEntity<InstanceInfo> response = webClient.put()
76+
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}")
77+
.queryParam("status", info.getStatus().toString())
78+
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()).build(appName, id))
7879
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
7980
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
8081
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(InstanceInfo.class).block();
@@ -95,22 +96,22 @@ public EurekaHttpResponse<InstanceInfo> sendHeartBeat(String appName, String id,
9596
@Override
9697
public EurekaHttpResponse<Void> statusUpdate(String appName, String id, InstanceStatus newStatus,
9798
InstanceInfo info) {
98-
String urlPath = "apps/" + appName + '/' + id + "/status?value=" + newStatus.name() + "&lastDirtyTimestamp="
99-
+ info.getLastDirtyTimestamp().toString();
100-
101-
return webClient.put().uri(urlPath).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
102-
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
103-
.map(this::eurekaHttpResponse).block();
99+
return webClient.put()
100+
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}/status").queryParam("value", newStatus.name())
101+
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()).build(appName, id))
102+
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).retrieve()
103+
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
104+
.block();
104105
}
105106

106107
@Override
107108
public EurekaHttpResponse<Void> deleteStatusOverride(String appName, String id, InstanceInfo info) {
108-
String urlPath = "apps/" + appName + '/' + id + "/status?lastDirtyTimestamp="
109-
+ info.getLastDirtyTimestamp().toString();
110-
111-
return webClient.delete().uri(urlPath).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
112-
.retrieve().onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity()
113-
.map(this::eurekaHttpResponse).block();
109+
return webClient.delete()
110+
.uri(uriBuilder -> uriBuilder.path("apps/{appName}/{id}/status")
111+
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString()).build(appName, id))
112+
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).retrieve()
113+
.onStatus(HttpStatusCode::isError, this::ignoreError).toBodilessEntity().map(this::eurekaHttpResponse)
114+
.block();
114115
}
115116

116117
@Override
@@ -119,13 +120,11 @@ public EurekaHttpResponse<Applications> getApplications(String... regions) {
119120
}
120121

121122
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath, String[] regions) {
122-
String url = urlPath;
123-
124-
if (regions != null && regions.length > 0) {
125-
url = url + (urlPath.contains("?") ? "&" : "?") + "regions=" + StringUtil.join(regions);
126-
}
123+
Optional<String> regionsParam = (regions != null && regions.length > 0) ? Optional.of(StringUtil.join(regions))
124+
: Optional.empty();
127125

128-
ResponseEntity<Applications> response = webClient.get().uri(url)
126+
ResponseEntity<Applications> response = webClient.get()
127+
.uri(uriBuilder -> uriBuilder.path(urlPath).queryParamIfPresent("regions", regionsParam).build())
129128
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
130129
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
131130
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(Applications.class).block();
@@ -156,7 +155,9 @@ public EurekaHttpResponse<Applications> getSecureVip(String secureVipAddress, St
156155
@Override
157156
public EurekaHttpResponse<Application> getApplication(String appName) {
158157

159-
ResponseEntity<Application> response = webClient.get().uri("apps/" + appName)
158+
ResponseEntity<Application> response = webClient.get()
159+
.uri(uriBuilder -> uriBuilder.path("apps/{appName}")
160+
.build(appName))
160161
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
161162
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(Application.class).block();
162163

@@ -170,16 +171,17 @@ public EurekaHttpResponse<Application> getApplication(String appName) {
170171

171172
@Override
172173
public EurekaHttpResponse<InstanceInfo> getInstance(String appName, String id) {
173-
return getInstanceInternal("apps/" + appName + '/' + id);
174+
return getInstanceInternal("apps", appName, id);
174175
}
175176

176177
@Override
177178
public EurekaHttpResponse<InstanceInfo> getInstance(String id) {
178-
return getInstanceInternal("instances/" + id);
179+
return getInstanceInternal("instances", id);
179180
}
180181

181-
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String urlPath) {
182-
ResponseEntity<InstanceInfo> response = webClient.get().uri(urlPath)
182+
private EurekaHttpResponse<InstanceInfo> getInstanceInternal(String... pathSegments) {
183+
ResponseEntity<InstanceInfo> response = webClient.get()
184+
.uri(uriBuilder -> uriBuilder.pathSegment(pathSegments).build())
183185
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).retrieve()
184186
.onStatus(HttpStatusCode::isError, this::ignoreError).toEntity(InstanceInfo.class).block();
185187

0 commit comments

Comments
 (0)