Ignore response body in eureka client on 404 error.
This allows heartbeats to proceed as normal. Fixes gh-4145
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.netflix.eureka.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
@@ -44,8 +46,11 @@ import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
|
||||
import org.springframework.cloud.configuration.SSLContextFactory;
|
||||
import org.springframework.cloud.configuration.TlsProperties;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
@@ -113,7 +118,9 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
}
|
||||
|
||||
private RestTemplate restTemplate(String serviceUrl) {
|
||||
RestTemplate restTemplate = restTemplate();
|
||||
ClientHttpRequestFactory requestFactory = this.eurekaClientHttpRequestFactorySupplier
|
||||
.get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null));
|
||||
RestTemplate restTemplate = new RestTemplate(requestFactory);
|
||||
|
||||
try {
|
||||
URI serviceURI = new URI(serviceUrl);
|
||||
@@ -132,13 +139,15 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
restTemplate.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
|
||||
restTemplate.setErrorHandler(new ErrorHandler());
|
||||
|
||||
return restTemplate;
|
||||
}
|
||||
restTemplate.getInterceptors().add((request, body, execution) -> {
|
||||
ClientHttpResponse response = execution.execute(request, body);
|
||||
if (!response.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
|
||||
return response;
|
||||
}
|
||||
return new NotFoundHttpResponse(response);
|
||||
});
|
||||
|
||||
private RestTemplate restTemplate() {
|
||||
ClientHttpRequestFactory requestFactory = this.eurekaClientHttpRequestFactorySupplier
|
||||
.get(this.sslContext.orElse(null), this.hostnameVerifier.orElse(null));
|
||||
return new RestTemplate(requestFactory);
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,11 +181,6 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
@Override
|
||||
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc,
|
||||
JsonSerializer<?> serializer) {
|
||||
/*
|
||||
* if (beanDesc.getBeanClass().isAssignableFrom(Applications.class)) {
|
||||
* return new ApplicationsJsonBeanSerializer((BeanSerializerBase)
|
||||
* serializer, keyFormatter); }
|
||||
*/
|
||||
if (beanDesc.getBeanClass().isAssignableFrom(InstanceInfo.class)) {
|
||||
return new InstanceInfoJsonBeanSerializer((BeanSerializerBase) serializer, false);
|
||||
}
|
||||
@@ -189,6 +193,50 @@ public class RestTemplateTransportClientFactory implements TransportClientFactor
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Response that ignores body, specifically for 404 errors.
|
||||
*/
|
||||
private static class NotFoundHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private final ClientHttpResponse response;
|
||||
|
||||
NotFoundHttpResponse(ClientHttpResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpStatusCode getStatusCode() throws IOException {
|
||||
return response.getStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() throws IOException {
|
||||
return response.getRawStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return response.getStatusText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
response.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
// ignore body on 404 for heartbeat, see gh-4145
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return response.getHeaders();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ErrorHandler extends DefaultResponseErrorHandler {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.resolver.EurekaEndpoint;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.TransportClientFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -151,6 +152,12 @@ public class WebClientTransportClientFactory implements TransportClientFactory {
|
||||
newResponse.body((clientHttpResponse, context) -> clientHttpResponse.getBody());
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
if (clientResponse.statusCode().equals(HttpStatus.NOT_FOUND)) {
|
||||
ClientResponse newResponse = clientResponse.mutate().statusCode(clientResponse.statusCode())
|
||||
// ignore body on 404 for heartbeat, see gh-4145
|
||||
.body(Flux.empty()).build();
|
||||
return Mono.just(newResponse);
|
||||
}
|
||||
return Mono.just(clientResponse);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.netflix.eureka.http;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.shared.Applications;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpClient;
|
||||
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -48,8 +49,9 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
|
||||
@Test
|
||||
void testSendHeartBeat() {
|
||||
assertThat(eurekaHttpClient.sendHeartBeat("test", "test", info, null).getStatusCode())
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
EurekaHttpResponse<InstanceInfo> response = eurekaHttpClient.sendHeartBeat("test", "test", info, null);
|
||||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(response.getEntity()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -58,6 +60,12 @@ abstract class AbstractEurekaHttpClientTests {
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendHeartBeatFourOFourWithBody() {
|
||||
assertThat(eurekaHttpClient.sendHeartBeat("fourOFourWithBody", "test", info, null).getStatusCode())
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStatusUpdate() {
|
||||
assertThat(eurekaHttpClient.statusUpdate("test", "test", InstanceInfo.InstanceStatus.UP, info).getStatusCode())
|
||||
|
||||
@@ -118,6 +118,11 @@ public class EurekaServerMockApplication {
|
||||
if ("fourOFour".equals(appName)) {
|
||||
return new ResponseEntity(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if ("fourOFourWithBody".equals(appName)) {
|
||||
return new ResponseEntity(
|
||||
"{ \"error\": \"Not Found\", \"message\": null, \"path\": \"/1\", \"requestId\": \"9e5d3244-1\", \"status\": 404, \"timestamp\": \"2023-03-04T03:31:20.810+00:00\" }",
|
||||
HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(new InstanceInfo(null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, 0, null, null, null, null, null, null, null, new HashMap<>(), 0L, 0L, null, null),
|
||||
HttpStatus.OK);
|
||||
|
||||
Reference in New Issue
Block a user