package org.apereo.cas.web.report;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.monitor.HealthCheckMonitor;
import org.apereo.cas.monitor.HealthStatus;
import org.apereo.cas.monitor.Monitor;
import org.apereo.cas.util.JsonUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.WebAsyncTask;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Reports overall CAS health based on the observations of the configured {@link HealthCheckMonitor} instance.
*
* @author Marvin S. Addison
* @since 3.5
*/
public class HealthCheckController extends BaseCasMvcEndpoint {
private final Monitor<HealthStatus> healthCheckMonitor;
private CasConfigurationProperties casProperties;
public HealthCheckController(final Monitor<HealthStatus> healthCheckMonitor, final CasConfigurationProperties casProperties) {
super("status", StringUtils.EMPTY, casProperties.getMonitor().getEndpoints().getStatus(), casProperties);
this.healthCheckMonitor = healthCheckMonitor;
this.casProperties = casProperties;
}
/**
* Handle request.
*
* @param request the request
* @param response the response
* @return the model and view
* @throws Exception the exception
*/
@GetMapping
@ResponseBody
protected WebAsyncTask<HealthStatus> handleRequestInternal(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
ensureEndpointAccessIsAuthorized(request, response);
final Callable<HealthStatus> asyncTask = () -> {
final HealthStatus healthStatus = healthCheckMonitor.observe();
response.setStatus(healthStatus.getCode().value());
if (StringUtils.equals(request.getParameter("format"), "json")) {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
JsonUtils.render(healthStatus.getDetails(), response);
} else {
final StringBuilder sb = new StringBuilder();
sb.append("Health: ").append(healthStatus.getCode());
final AtomicInteger i = new AtomicInteger();
healthStatus.getDetails().forEach((name, status) -> {
response.addHeader("X-CAS-" + name, String.format("%s;%s", status.getCode(), status.getDescription()));
sb.append("\n\n\t").append(i.incrementAndGet()).append('.').append(name).append(": ");
sb.append(status.getCode());
if (status.getDescription() != null) {
sb.append(" - ").append(status.getDescription());
}
});
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
try (Writer writer = response.getWriter()) {
IOUtils.copy(new ByteArrayInputStream(sb.toString().getBytes(response.getCharacterEncoding())),
writer,
StandardCharsets.UTF_8);
writer.flush();
}
}
return null;
};
return new WebAsyncTask<>(casProperties.getHttpClient().getAsyncTimeout(), asyncTask);
}
}