Commit d36ae2eb by Johannes Edmeier

Fix: no status update when recieving response with no body but compatible content-type

fixes #780
parent 8fb43be4
......@@ -31,6 +31,7 @@ import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.ClientResponse;
......@@ -78,29 +79,32 @@ public class StatusUpdater {
}
protected Mono<StatusInfo> convertStatusInfo(ClientResponse response) {
if (response.headers()
.contentType()
.map(mt -> mt.isCompatibleWith(MediaType.APPLICATION_JSON) ||
mt.isCompatibleWith(ACTUATOR_V2_MEDIATYPE))
.orElse(false)) {
Boolean hasCompatibleContentType = response.headers()
.contentType()
.map(mt -> mt.isCompatibleWith(MediaType.APPLICATION_JSON) ||
mt.isCompatibleWith(ACTUATOR_V2_MEDIATYPE))
.orElse(false);
StatusInfo statusInfoFromStatus = this.getStatusInfoFromStatus(response.statusCode(), emptyMap());
if (hasCompatibleContentType) {
return response.bodyToMono(RESPONSE_TYPE).map(body -> {
if (body.get("status") instanceof String) {
return StatusInfo.from(body);
}
return getStatusInfoFromStatus(response, body);
});
return getStatusInfoFromStatus(response.statusCode(), body);
}).defaultIfEmpty(statusInfoFromStatus);
}
return response.bodyToMono(Void.class).then(Mono.just(this.getStatusInfoFromStatus(response, emptyMap())));
return response.bodyToMono(Void.class).then(Mono.just(statusInfoFromStatus));
}
@SuppressWarnings("unchecked")
protected StatusInfo getStatusInfoFromStatus(ClientResponse response, Map<String, ?> body) {
if (response.statusCode().is2xxSuccessful()) {
protected StatusInfo getStatusInfoFromStatus(HttpStatus httpStatus, Map<String, ?> body) {
if (httpStatus.is2xxSuccessful()) {
return StatusInfo.ofUp();
}
Map<String, Object> details = new LinkedHashMap<>();
details.put("status", response.statusCode().value());
details.put("error", response.statusCode().getReasonPhrase());
details.put("status", httpStatus.value());
details.put("error", httpStatus.getReasonPhrase());
if (body.get("details") instanceof Map) {
details.putAll((Map<? extends String, ?>) body.get("details"));
} else {
......
......@@ -73,7 +73,7 @@ public class StatusUpdaterTest {
}
@Test
public void test_update_statusChanged() {
public void should_change_status_to_down() {
String body = "{ \"status\" : \"UP\", \"details\" : { \"foo\" : \"bar\" } }";
wireMock.stubFor(get("/health").willReturn(
okForContentType(ActuatorMediaType.V2_JSON, body).withHeader("Content-Length",
......@@ -109,7 +109,7 @@ public class StatusUpdaterTest {
}
@Test
public void test_update_statusUnchanged() {
public void should_not_change_status() {
String body = "{ \"status\" : \"UNKNOWN\" }";
wireMock.stubFor(
get("/health").willReturn(okJson(body).withHeader("Content-Type", Integer.toString(body.length()))));
......@@ -124,7 +124,7 @@ public class StatusUpdaterTest {
}
@Test
public void test_update_up_noBody() {
public void should_change_status_to_up() {
wireMock.stubFor(get("/health").willReturn(ok()));
StepVerifier.create(eventStore)
......@@ -140,7 +140,7 @@ public class StatusUpdaterTest {
}
@Test
public void test_update_down() {
public void should_change_status_to_down_with_details() {
String body = "{ \"foo\" : \"bar\" }";
wireMock.stubFor(get("/health").willReturn(
status(503).withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
......@@ -161,7 +161,7 @@ public class StatusUpdaterTest {
}
@Test
public void test_update_down_noBody() {
public void should_change_status_to_down_without_details_incompatible_content_type() {
wireMock.stubFor(get("/health").willReturn(status(503)));
StepVerifier.create(eventStore)
......@@ -179,7 +179,26 @@ public class StatusUpdaterTest {
}
@Test
public void test_update_offline() {
public void should_change_status_to_down_without_details_no_body() {
wireMock.stubFor(
get("/health").willReturn(status(503).withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)));
StepVerifier.create(eventStore)
.expectSubscription()
.then(() -> StepVerifier.create(updater.updateStatus(instance.getId())).verifyComplete())
.assertNext(event -> assertThat(event).isInstanceOf(InstanceStatusChangedEvent.class))
.thenCancel()
.verify();
StepVerifier.create(repository.find(instance.getId())).assertNext(app -> {
assertThat(app.getStatusInfo().getStatus()).isEqualTo("DOWN");
assertThat(app.getStatusInfo().getDetails()).containsEntry("status", 503)
.containsEntry("error", "Service Unavailable");
}).verifyComplete();
}
@Test
public void should_change_status_to_offline() {
wireMock.stubFor(get("/health").willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER)));
StepVerifier.create(eventStore)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment