Skip to content

Commit

Permalink
EPA-105: replace with Undertow
Browse files Browse the repository at this point in the history
  • Loading branch information
michelealbanese-oviva committed May 6, 2024
1 parent 019f04e commit 73f30a0
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@
import com.oviva.ehealthid.relyingparty.svc.TokenIssuerImpl;
import com.oviva.ehealthid.relyingparty.util.DiscoveryJwkSetSource;
import com.oviva.ehealthid.relyingparty.ws.App;
import com.oviva.ehealthid.relyingparty.ws.ManagementApp;
import com.oviva.ehealthid.relyingparty.ws.HealthEndpoint;
import com.oviva.ehealthid.relyingparty.ws.MetricsEndpoint;
import io.micrometer.core.instrument.binder.cache.CaffeineCacheMetrics;
import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.undertow.Handlers;
import io.undertow.Undertow;
import jakarta.ws.rs.SeBootstrap;
import jakarta.ws.rs.SeBootstrap.Configuration;
import jakarta.ws.rs.core.UriBuilder;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.time.Clock;
Expand All @@ -60,7 +65,7 @@ public class Main implements AutoCloseable {
private final ConfigProvider configProvider;

private SeBootstrap.Instance server;
private SeBootstrap.Instance managementServer;
private Undertow managementServer;

private CountDownLatch shutdown = new CountDownLatch(1);

Expand Down Expand Up @@ -92,7 +97,10 @@ public URI baseUri() {
}

public URI managementBaseUri() {
return managementServer.configuration().baseUri();
var baseUri = server.configuration().baseUri();
var address = (InetSocketAddress) managementServer.getListenerInfo().get(0).getAddress();

return UriBuilder.fromUri(baseUri).port(address.getPort()).build();
}

public void start() throws ExecutionException, InterruptedException {
Expand Down Expand Up @@ -150,14 +158,16 @@ public void start() throws ExecutionException, InterruptedException {
logger.atInfo().log("Magic at {} ({})", config.baseUri(), localUri);

managementServer =
SeBootstrap.start(
new ManagementApp(meterRegistry),
Configuration.builder().host(config.host()).port(config.managementPort()).build())
.toCompletableFuture()
.get();
Undertow.builder()
.addHttpListener(config.managementPort(), config.host())
.setHandler(
Handlers.path()
.addExactPath(HealthEndpoint.PATH, new HealthEndpoint())
.addExactPath(MetricsEndpoint.PATH, new MetricsEndpoint(meterRegistry)))
.build();
managementServer.start();

var metricsLocalUri = managementServer.configuration().baseUri();
logger.atInfo().log("Management Server at {} ({})", config.baseUri(), metricsLocalUri);
logger.atInfo().log("Management Server can be found at port {}", config.managementPort());
}

private AuthenticationFlow buildAuthFlow(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
package com.oviva.ehealthid.relyingparty.ws;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;

@Path("/health")
public class HealthEndpoint {
public class HealthEndpoint implements HttpHandler {
public static final String PATH = "/health";

private static final int HTTP_METHOD_NOT_ALLOWED = 405;
private static final int HTTP_OK = 200;

private static final String STATUS_UP = "{\"status\":\"UP\"}";

@GET
public Response get() {
// For now if this endpoint is reachable then the service is up. There is no hard dependency
// that could be down.
return Response.ok(STATUS_UP).type(MediaType.APPLICATION_JSON_TYPE).build();
@Override
public void handleRequest(HttpServerExchange httpServerExchange) {
if (!httpServerExchange.getRequestMethod().equals(HttpString.tryFromString("GET"))) {
httpServerExchange.setStatusCode(HTTP_METHOD_NOT_ALLOWED);
httpServerExchange.getResponseSender().send("");
} else {
// For now if this endpoint is reachable then the service is up.
// There is no hard dependency that could be down.
httpServerExchange.setStatusCode(HTTP_OK);
httpServerExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
httpServerExchange.getResponseSender().send(STATUS_UP);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics;
import io.micrometer.core.instrument.binder.system.ProcessorMetrics;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;

@Path("/metrics")
public class MetricsEndpoint {
public class MetricsEndpoint implements HttpHandler {
public static final String PATH = "/metrics";
private static final int HTTP_OK = 200;
private static final int HTTP_METHOD_NOT_ALLOWED = 405;

private final PrometheusMeterRegistry registry;

Expand All @@ -26,9 +28,17 @@ public MetricsEndpoint(PrometheusMeterRegistry registry) {
new JvmThreadMetrics().bindTo(this.registry);
}

@GET
@Produces(MediaType.TEXT_PLAIN)
public String get() {
return registry.scrape();
@Override
public void handleRequest(HttpServerExchange httpServerExchange) {
if (!httpServerExchange.getRequestMethod().equals(HttpString.tryFromString("GET"))) {
httpServerExchange.setStatusCode(HTTP_METHOD_NOT_ALLOWED);
httpServerExchange.getResponseSender().send("");
} else {
httpServerExchange.setStatusCode(HTTP_OK);
httpServerExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");

var metricsContents = registry.scrape();
httpServerExchange.getResponseSender().send(metricsContents);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ static void afterAll() throws Exception {

@Test
void run_smokeTest() {

var baseUri = application.baseUri();
var managementBaseUri = application.managementBaseUri();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.oviva.ehealthid.relyingparty.ws;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import io.undertow.io.Sender;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.HttpString;
import jakarta.ws.rs.core.Response.Status;
import org.junit.jupiter.api.Test;

Expand All @@ -12,9 +18,36 @@ void get() {
var sut = new HealthEndpoint();

// when
var res = sut.get();
var httpServerExchange = mock(HttpServerExchange.class);
var headers = mock(HeaderMap.class);
var sender = mock(Sender.class);

when(httpServerExchange.getResponseHeaders()).thenReturn(headers);
when(httpServerExchange.getResponseSender()).thenReturn(sender);
when(httpServerExchange.getRequestMethod()).thenReturn(HttpString.tryFromString("GET"));

sut.handleRequest(httpServerExchange);

// then
verify(httpServerExchange).setStatusCode(Status.OK.getStatusCode());
}

@Test
void methodNotAllowed() {
var sut = new HealthEndpoint();

// when
var httpServerExchange = mock(HttpServerExchange.class);
var headers = mock(HeaderMap.class);
var sender = mock(Sender.class);

when(httpServerExchange.getResponseHeaders()).thenReturn(headers);
when(httpServerExchange.getResponseSender()).thenReturn(sender);
when(httpServerExchange.getRequestMethod()).thenReturn(HttpString.tryFromString("POST"));

sut.handleRequest(httpServerExchange);

// then
assertEquals(Status.OK.getStatusCode(), res.getStatus());
verify(httpServerExchange).setStatusCode(Status.METHOD_NOT_ALLOWED.getStatusCode());
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
package com.oviva.ehealthid.relyingparty.ws;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.undertow.io.Sender;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.HttpString;
import jakarta.ws.rs.core.Response.Status;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class MetricsEndpointTest {

@Captor ArgumentCaptor<String> responseCaptor;

@Test
void get() {
// when
var httpServerExchange = mock(HttpServerExchange.class);
var headers = mock(HeaderMap.class);
var sender = mock(Sender.class);

when(httpServerExchange.getResponseHeaders()).thenReturn(headers);
when(httpServerExchange.getResponseSender()).thenReturn(sender);
when(httpServerExchange.getRequestMethod()).thenReturn(HttpString.tryFromString("GET"));

// given
var prometheusMeterRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
Expand All @@ -21,9 +44,30 @@ void get() {
var sut = new MetricsEndpoint(prometheusMeterRegistry);

// when
var res = sut.get();
sut.handleRequest(httpServerExchange);

// then
verify(sender).send(responseCaptor.capture());
assertTrue(responseCaptor.getValue().contains("test_counter_total 2.0"));
}

@Test
void methodNotAllowed() {
// when
var httpServerExchange = mock(HttpServerExchange.class);
var sender = mock(Sender.class);

when(httpServerExchange.getResponseSender()).thenReturn(sender);
when(httpServerExchange.getRequestMethod()).thenReturn(HttpString.tryFromString("POST"));

// given
var prometheusMeterRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
var sut = new MetricsEndpoint(prometheusMeterRegistry);

// when
sut.handleRequest(httpServerExchange);

// then
assertTrue(res.contains("test_counter_total 2.0"));
verify(httpServerExchange).setStatusCode(Status.METHOD_NOT_ALLOWED.getStatusCode());
}
}

0 comments on commit 73f30a0

Please sign in to comment.