Add a health check handler to the Noise-over-WebSocket pipeline

This commit is contained in:
Jon Chambers 2024-05-22 13:11:13 -04:00 committed by Jon Chambers
parent 907ff89011
commit 097bedcb9b
3 changed files with 24 additions and 6 deletions

View File

@ -41,6 +41,7 @@ public class NoiseWebSocketTunnelServer implements Managed {
static final String AUTHENTICATED_SERVICE_PATH = "/authenticated"; static final String AUTHENTICATED_SERVICE_PATH = "/authenticated";
static final String ANONYMOUS_SERVICE_PATH = "/anonymous"; static final String ANONYMOUS_SERVICE_PATH = "/anonymous";
static final String HEALTH_CHECK_PATH = "/health-check";
private static final Logger log = LoggerFactory.getLogger(NoiseWebSocketTunnelServer.class); private static final Logger log = LoggerFactory.getLogger(NoiseWebSocketTunnelServer.class);
@ -96,7 +97,7 @@ public class NoiseWebSocketTunnelServer implements Managed {
.addLast(new HttpObjectAggregator(Noise.MAX_PACKET_LEN)) .addLast(new HttpObjectAggregator(Noise.MAX_PACKET_LEN))
// The WebSocket opening handshake handler will remove itself from the pipeline once it has received a valid WebSocket upgrade // The WebSocket opening handshake handler will remove itself from the pipeline once it has received a valid WebSocket upgrade
// request and passed it down the pipeline // request and passed it down the pipeline
.addLast(new WebSocketOpeningHandshakeHandler(AUTHENTICATED_SERVICE_PATH, ANONYMOUS_SERVICE_PATH)) .addLast(new WebSocketOpeningHandshakeHandler(AUTHENTICATED_SERVICE_PATH, ANONYMOUS_SERVICE_PATH, HEALTH_CHECK_PATH))
.addLast(new WebSocketServerProtocolHandler("/", true)) .addLast(new WebSocketServerProtocolHandler("/", true))
.addLast(new RejectUnsupportedMessagesHandler()) .addLast(new RejectUnsupportedMessagesHandler())
// The WebSocket handshake complete listener will replace itself with an appropriate Noise handshake handler once // The WebSocket handshake complete listener will replace itself with an appropriate Noise handshake handler once

View File

@ -19,10 +19,15 @@ class WebSocketOpeningHandshakeHandler extends ChannelInboundHandlerAdapter {
private final String authenticatedPath; private final String authenticatedPath;
private final String anonymousPath; private final String anonymousPath;
private final String healthCheckPath;
WebSocketOpeningHandshakeHandler(final String authenticatedPath,
final String anonymousPath,
final String healthCheckPath) {
WebSocketOpeningHandshakeHandler(final String authenticatedPath, final String anonymousPath) {
this.authenticatedPath = authenticatedPath; this.authenticatedPath = authenticatedPath;
this.anonymousPath = anonymousPath; this.anonymousPath = anonymousPath;
this.healthCheckPath = healthCheckPath;
} }
@Override @Override
@ -43,6 +48,8 @@ class WebSocketOpeningHandshakeHandler extends ChannelInboundHandlerAdapter {
} else { } else {
closeConnectionWithStatus(context, request, HttpResponseStatus.UPGRADE_REQUIRED); closeConnectionWithStatus(context, request, HttpResponseStatus.UPGRADE_REQUIRED);
} }
} else if (healthCheckPath.equals(request.uri())) {
closeConnectionWithStatus(context, request, HttpResponseStatus.NO_CONTENT);
} else { } else {
closeConnectionWithStatus(context, request, HttpResponseStatus.NOT_FOUND); closeConnectionWithStatus(context, request, HttpResponseStatus.NOT_FOUND);
} }

View File

@ -15,7 +15,6 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.ReferenceCountUtil;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
@ -27,10 +26,12 @@ class WebSocketOpeningHandshakeHandlerTest extends AbstractLeakDetectionTest {
private static final String AUTHENTICATED_PATH = "/authenticated"; private static final String AUTHENTICATED_PATH = "/authenticated";
private static final String ANONYMOUS_PATH = "/anonymous"; private static final String ANONYMOUS_PATH = "/anonymous";
private static final String HEALTH_CHECK_PATH = "/health-check";
@BeforeEach @BeforeEach
void setUp() { void setUp() {
embeddedChannel = new EmbeddedChannel(new WebSocketOpeningHandshakeHandler(AUTHENTICATED_PATH, ANONYMOUS_PATH)); embeddedChannel =
new EmbeddedChannel(new WebSocketOpeningHandshakeHandler(AUTHENTICATED_PATH, ANONYMOUS_PATH, HEALTH_CHECK_PATH));
} }
@ParameterizedTest @ParameterizedTest
@ -50,6 +51,16 @@ class WebSocketOpeningHandshakeHandlerTest extends AbstractLeakDetectionTest {
} }
} }
@Test
void handleHealthCheckRequest() {
final FullHttpRequest request = buildRequest(HttpMethod.GET, HEALTH_CHECK_PATH, new DefaultHttpHeaders());
embeddedChannel.writeOneInbound(request);
assertEquals(0, request.refCnt());
assertHttpResponse(HttpResponseStatus.NO_CONTENT);
}
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = { AUTHENTICATED_PATH, ANONYMOUS_PATH }) @ValueSource(strings = { AUTHENTICATED_PATH, ANONYMOUS_PATH })
void handleUpgradeRequired(final String path) { void handleUpgradeRequired(final String path) {
@ -89,7 +100,6 @@ class WebSocketOpeningHandshakeHandlerTest extends AbstractLeakDetectionTest {
final FullHttpResponse response = assertInstanceOf(FullHttpResponse.class, embeddedChannel.outboundMessages().poll()); final FullHttpResponse response = assertInstanceOf(FullHttpResponse.class, embeddedChannel.outboundMessages().poll());
//noinspection DataFlowIssue
assertEquals(expectedStatus, response.status()); assertEquals(expectedStatus, response.status());
} }
@ -99,6 +109,6 @@ class WebSocketOpeningHandshakeHandlerTest extends AbstractLeakDetectionTest {
path, path,
Unpooled.buffer(0), Unpooled.buffer(0),
headers, headers,
new DefaultHttpHeaders(true)); new DefaultHttpHeaders());
} }
} }