0
0
mirror of https://github.com/signalapp/Signal-Server.git synced 2024-09-19 19:42:18 +02:00

Upgrade to dropwizard 3.0

This commit is contained in:
Chris Eager 2023-11-16 17:57:48 -06:00 committed by GitHub
parent 041aa8639a
commit 84b56ae1b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 327 additions and 307 deletions

32
pom.xml
View File

@ -42,14 +42,18 @@
<braintree.version>3.27.0</braintree.version>
<commons-csv.version>1.10.0</commons-csv.version>
<commons-io.version>2.14.0</commons-io.version>
<dropwizard.version>2.1.9</dropwizard.version>
<dropwizard.version>3.0.4</dropwizard.version>
<dropwizard-metrics-datadog.version>1.1.13</dropwizard-metrics-datadog.version>
<google-cloud-libraries.version>26.25.0</google-cloud-libraries.version>
<grpc.version>1.58.0</grpc.version> <!-- should be kept in sync with the value from Google libraries-bom -->
<gson.version>2.10.1</gson.version>
<jackson.version>2.13.5</jackson.version>
<!-- several libraries (AWS, Google Cloud) use Apache http components transitively, and we need to align them -->
<httpcore.version>4.4.16</httpcore.version>
<httpclient.version>4.5.14</httpclient.version>
<jackson.version>2.16.0</jackson.version>
<jaxb.version>2.3.1</jaxb.version>
<junit-pioneer.version>2.1.0</junit-pioneer.version>
<jsr305.version>3.0.2</jsr305.version>
<kotlin.version>1.9.10</kotlin.version>
<kotlinx-serialization.version>1.5.1</kotlinx-serialization.version>
<lettuce.version>6.2.6.RELEASE</lettuce.version>
@ -66,7 +70,7 @@
<reactor-bom.version>2022.0.12</reactor-bom.version> <!-- 3.5.x, see https://github.com/reactor/reactor#bom-versioning-scheme -->
<resilience4j.version>1.7.0</resilience4j.version>
<semver4j.version>3.1.0</semver4j.version>
<slf4j.version>1.7.36</slf4j.version>
<slf4j.version>2.0.9</slf4j.version>
<stripe.version>23.10.0</stripe.version>
<swagger.version>2.2.17</swagger.version>
<vavr.version>0.10.4</vavr.version>
@ -262,6 +266,11 @@
<artifactId>braintree-java</artifactId>
<version>${braintree.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>${jsr305.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
@ -285,6 +294,16 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>${httpcore.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
@ -296,9 +315,10 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>2.35.1</version>
<groupId>org.wiremock</groupId>
<!-- use standalone until Dropwizard 4 + jakarta.* -->
<artifactId>wiremock-standalone</artifactId>
<version>3.3.1</version>
<scope>test</scope>
<exclusions>
<exclusion>

View File

@ -165,12 +165,6 @@
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-testing</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -195,7 +189,7 @@
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-api</artifactId>
<artifactId>websocket-jetty-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -380,12 +374,6 @@
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
@ -396,10 +384,6 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>

View File

@ -5,7 +5,7 @@
package org.whispersystems.textsecuregcm;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.Configuration;
import io.dropwizard.core.Configuration;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;

View File

@ -15,14 +15,14 @@ import com.google.cloud.logging.LoggingOptions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import io.dropwizard.Application;
import io.dropwizard.auth.AuthFilter;
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
import io.dropwizard.auth.basic.BasicCredentials;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.setup.Bootstrap;
import io.dropwizard.core.setup.Environment;
import io.grpc.ServerBuilder;
import io.grpc.ServerInterceptors;
import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder;
@ -50,6 +50,7 @@ import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletRegistration;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.glassfish.jersey.server.ServerProperties;
import org.signal.event.AdminEventLogger;
import org.signal.event.GoogleCloudAdminEventLogger;
@ -91,11 +92,11 @@ import org.whispersystems.textsecuregcm.configuration.secrets.SecretStore;
import org.whispersystems.textsecuregcm.configuration.secrets.SecretsModule;
import org.whispersystems.textsecuregcm.controllers.AccountController;
import org.whispersystems.textsecuregcm.controllers.AccountControllerV2;
import org.whispersystems.textsecuregcm.controllers.ArchiveController;
import org.whispersystems.textsecuregcm.controllers.ArtController;
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV2;
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV3;
import org.whispersystems.textsecuregcm.controllers.AttachmentControllerV4;
import org.whispersystems.textsecuregcm.controllers.ArchiveController;
import org.whispersystems.textsecuregcm.controllers.CallLinkController;
import org.whispersystems.textsecuregcm.controllers.CertificateController;
import org.whispersystems.textsecuregcm.controllers.ChallengeController;
@ -706,7 +707,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
///
WebSocketEnvironment<AuthenticatedAccount> webSocketEnvironment = new WebSocketEnvironment<>(environment,
config.getWebSocketConfiguration(), 90000);
config.getWebSocketConfiguration(), Duration.ofMillis(90000));
webSocketEnvironment.setAuthenticator(new WebSocketAccountAuthenticator(accountAuthenticator));
webSocketEnvironment.setConnectListener(
new AuthenticatedConnectListener(receiptSender, messagesManager, pushNotificationManager,
@ -826,7 +827,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
}
WebSocketEnvironment<AuthenticatedAccount> provisioningEnvironment = new WebSocketEnvironment<>(environment,
webSocketEnvironment.getRequestLog(), 60000);
webSocketEnvironment.getRequestLog(), Duration.ofMillis(60000));
provisioningEnvironment.jersey().register(new WebsocketRefreshApplicationEventListener(accountsManager, clientPresenceManager));
provisioningEnvironment.setConnectListener(new ProvisioningConnectListener(provisioningManager));
provisioningEnvironment.jersey().register(new MetricsApplicationEventListener(TrafficSource.WEBSOCKET, clientReleaseManager));
@ -840,6 +841,8 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
webSocketEnvironment.jersey().property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
provisioningEnvironment.jersey().property(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE);
JettyWebSocketServletContainerInitializer.configure(environment.getApplicationContext(), null);
WebSocketResourceProviderFactory<AuthenticatedAccount> webSocketServlet = new WebSocketResourceProviderFactory<>(
webSocketEnvironment, AuthenticatedAccount.class, config.getWebSocketConfiguration());
WebSocketResourceProviderFactory<AuthenticatedAccount> provisioningServlet = new WebSocketResourceProviderFactory<>(

View File

@ -5,11 +5,11 @@
package org.whispersystems.textsecuregcm.configuration;
import io.dropwizard.util.Strings;
import io.dropwizard.validation.ValidationMethod;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
public record GcpAttachmentsConfiguration(@NotBlank String domain,
@ -20,6 +20,6 @@ public record GcpAttachmentsConfiguration(@NotBlank String domain,
@SuppressWarnings("unused")
@ValidationMethod(message = "pathPrefix must be empty or start with /")
public boolean isPathPrefixValid() {
return Strings.isNullOrEmpty(pathPrefix) || pathPrefix.startsWith("/");
return StringUtils.isEmpty(pathPrefix) || pathPrefix.startsWith("/");
}
}

View File

@ -5,9 +5,6 @@
package org.whispersystems.textsecuregcm.gcp;
import io.dropwizard.util.Strings;
import javax.annotation.Nonnull;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
@ -16,6 +13,8 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;
public class CanonicalRequestGenerator {
private static final DateTimeFormatter SIMPLE_UTC_DATE = DateTimeFormatter.ofPattern("yyyyMMdd", Locale.US).withZone(ZoneOffset.UTC);
@ -43,7 +42,7 @@ public class CanonicalRequestGenerator {
final StringBuilder result = new StringBuilder("POST\n");
final StringBuilder resourcePathBuilder = new StringBuilder();
if (!Strings.isNullOrEmpty(pathPrefix)) {
if (StringUtils.isNotEmpty(pathPrefix)) {
resourcePathBuilder.append(pathPrefix);
}
resourcePathBuilder.append('/').append(URLEncoder.encode(key, StandardCharsets.UTF_8));

View File

@ -17,10 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import io.dropwizard.logging.AbstractAppenderFactory;
import io.dropwizard.logging.async.AsyncAppenderFactory;
import io.dropwizard.logging.filter.LevelFilterFactory;
import io.dropwizard.logging.layout.LayoutFactory;
import io.dropwizard.logging.common.AbstractAppenderFactory;
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
import io.dropwizard.logging.common.filter.LevelFilterFactory;
import io.dropwizard.logging.common.layout.LayoutFactory;
import java.time.Duration;
import java.util.Optional;
import javax.validation.constraints.NotEmpty;

View File

@ -7,7 +7,7 @@ package org.whispersystems.textsecuregcm.metrics;
import com.codahale.metrics.SharedMetricRegistries;
import com.google.common.annotations.VisibleForTesting;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.setup.Environment;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Metrics;

View File

@ -14,7 +14,7 @@ import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.ScheduledReporter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.dropwizard.metrics.BaseReporterFactory;
import io.dropwizard.metrics.common.BaseReporterFactory;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

View File

@ -8,7 +8,7 @@ package org.whispersystems.textsecuregcm.util.logging;
import ch.qos.logback.access.spi.IAccessEvent;
import ch.qos.logback.core.filter.Filter;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.dropwizard.logging.filter.FilterFactory;
import io.dropwizard.logging.common.filter.FilterFactory;
@JsonTypeName("requestLogEnabled")
class RequestLogEnabledFilterFactory implements FilterFactory<IAccessEvent> {

View File

@ -5,10 +5,10 @@
package org.whispersystems.textsecuregcm.workers;
import io.dropwizard.Application;
import io.dropwizard.cli.Cli;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.Cli;
import io.dropwizard.core.cli.EnvironmentCommand;
import io.dropwizard.core.setup.Environment;
import java.util.Objects;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

View File

@ -8,9 +8,9 @@ package org.whispersystems.textsecuregcm.workers;
import static com.codahale.metrics.MetricRegistry.name;
import com.fasterxml.jackson.databind.DeserializationFeature;
import io.dropwizard.Application;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.EnvironmentCommand;
import io.dropwizard.core.setup.Environment;
import io.lettuce.core.resource.ClientResources;
import java.time.Clock;
import java.util.Base64;

View File

@ -7,6 +7,11 @@ package org.whispersystems.textsecuregcm.workers;
import com.google.common.base.MoreObjects;
import com.google.protobuf.ByteString;
import io.dropwizard.core.cli.Command;
import io.dropwizard.core.setup.Bootstrap;
import java.security.InvalidKeyException;
import java.util.Base64;
import java.util.Set;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
@ -15,13 +20,6 @@ import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.protocol.ecc.ECPrivateKey;
import org.whispersystems.textsecuregcm.entities.MessageProtos;
import java.security.InvalidKeyException;
import java.util.Base64;
import java.util.Set;
import io.dropwizard.cli.Command;
import io.dropwizard.setup.Bootstrap;
public class CertificateCommand extends Command {
private static final Set<Integer> RESERVED_CERTIFICATE_IDS = Set.of(

View File

@ -5,8 +5,8 @@
package org.whispersystems.textsecuregcm.workers;
import io.dropwizard.cli.Command;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.core.cli.Command;
import io.dropwizard.core.setup.Bootstrap;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;

View File

@ -8,7 +8,7 @@ package org.whispersystems.textsecuregcm.workers;
import static com.codahale.metrics.MetricRegistry.name;
import com.fasterxml.jackson.databind.DeserializationFeature;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.setup.Environment;
import io.lettuce.core.resource.ClientResources;
import java.io.IOException;
import java.security.cert.CertificateException;

View File

@ -6,9 +6,9 @@
package org.whispersystems.textsecuregcm.workers;
import com.fasterxml.jackson.databind.DeserializationFeature;
import io.dropwizard.Application;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.EnvironmentCommand;
import io.dropwizard.core.setup.Environment;
import java.util.Optional;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

View File

@ -5,9 +5,9 @@
package org.whispersystems.textsecuregcm.workers;
import io.dropwizard.Application;
import io.dropwizard.cli.ServerCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.ServerCommand;
import io.dropwizard.core.setup.Environment;
import java.time.Duration;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

View File

@ -7,9 +7,10 @@ package org.whispersystems.textsecuregcm.workers;
import static com.codahale.metrics.MetricRegistry.name;
import io.dropwizard.Application;
import io.dropwizard.cli.ServerCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.ServerCommand;
import io.dropwizard.core.setup.Environment;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

View File

@ -5,8 +5,8 @@
package org.whispersystems.textsecuregcm.workers;
import io.dropwizard.cli.Command;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.core.cli.Command;
import io.dropwizard.core.setup.Bootstrap;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import org.whispersystems.textsecuregcm.WhisperServerVersion;

View File

@ -6,9 +6,9 @@
package org.whispersystems.textsecuregcm.workers;
import com.fasterxml.jackson.databind.DeserializationFeature;
import io.dropwizard.Application;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.EnvironmentCommand;
import io.dropwizard.core.setup.Environment;
import java.util.Optional;
import java.util.UUID;
import net.sourceforge.argparse4j.inf.Namespace;

View File

@ -6,9 +6,9 @@
package org.whispersystems.textsecuregcm.workers;
import com.fasterxml.jackson.databind.DeserializationFeature;
import io.dropwizard.Application;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.Application;
import io.dropwizard.core.cli.EnvironmentCommand;
import io.dropwizard.core.setup.Environment;
import java.util.List;
import java.util.UUID;

View File

@ -5,15 +5,14 @@
package org.whispersystems.textsecuregcm.workers;
import io.dropwizard.core.cli.Command;
import io.dropwizard.core.setup.Bootstrap;
import java.util.Base64;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import org.signal.libsignal.zkgroup.ServerPublicParams;
import org.signal.libsignal.zkgroup.ServerSecretParams;
import io.dropwizard.cli.Command;
import io.dropwizard.setup.Bootstrap;
import java.util.Base64;
public class ZkParamsCommand extends Command {
public ZkParamsCommand() {

View File

@ -19,7 +19,6 @@ import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.protobuf.InvalidProtocolBufferException;
import io.dropwizard.auth.Auth;
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
@ -28,9 +27,11 @@ import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
import io.dropwizard.testing.junit5.ResourceExtension;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
@ -57,6 +58,7 @@ import javax.ws.rs.core.Response;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.WriteCallback;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
@ -337,7 +339,7 @@ class AuthEnablementRefreshRequirementProviderTest {
provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("test", account, authenticatedDevice), new ProtobufWebSocketMessageFactory(),
Optional.empty(), 30000);
Optional.empty(), Duration.ofMillis(30000));
remoteEndpoint = mock(RemoteEndpoint.class);
Session session = mock(Session.class);
@ -363,9 +365,9 @@ class AuthEnablementRefreshRequirementProviderTest {
}
private SubProtocol.WebSocketResponseMessage verifyAndGetResponse(final RemoteEndpoint remoteEndpoint)
throws InvalidProtocolBufferException {
throws IOException {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
return SubProtocol.WebSocketMessage.parseFrom(responseBytesCaptor.getValue().array()).getResponse();
}

View File

@ -22,8 +22,10 @@ import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.Principal;
import java.time.Duration;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
@ -36,6 +38,7 @@ import javax.ws.rs.Path;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.WriteCallback;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.ContainerResponse;
@ -121,7 +124,7 @@ class MetricsRequestEventListenerTest {
}
@Test
void testActualRouteMessageSuccess() throws InvalidProtocolBufferException {
void testActualRouteMessageSuccess() throws IOException {
final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class);
when(applicationEventListener.onRequest(any())).thenReturn(listener);
@ -140,7 +143,7 @@ class MetricsRequestEventListenerTest {
new TestPrincipal("foo"),
new ProtobufWebSocketMessageFactory(),
Optional.empty(),
30000);
Duration.ofMillis(30000));
final Session session = mock(Session.class);
final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -163,7 +166,7 @@ class MetricsRequestEventListenerTest {
provider.onWebSocketBinary(message, 0, message.length);
final ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -187,7 +190,7 @@ class MetricsRequestEventListenerTest {
}
@Test
void testActualRouteMessageSuccessNoUserAgent() throws InvalidProtocolBufferException {
void testActualRouteMessageSuccessNoUserAgent() throws IOException {
final MetricsApplicationEventListener applicationEventListener = mock(MetricsApplicationEventListener.class);
when(applicationEventListener.onRequest(any())).thenReturn(listener);
@ -200,8 +203,10 @@ class MetricsRequestEventListenerTest {
final ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
final WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
final WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
final WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1",
applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
final Session session = mock(Session.class);
final RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -222,7 +227,7 @@ class MetricsRequestEventListenerTest {
provider.onWebSocketBinary(message, 0, message.length);
final ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);

View File

@ -137,7 +137,7 @@ class AccountsManagerTest {
//noinspection unchecked
asyncCommands = mock(RedisAdvancedClusterAsyncCommands.class);
when(asyncCommands.del(any())).thenReturn(MockRedisFuture.completedFuture(0L));
when(asyncCommands.del(any(String[].class))).thenReturn(MockRedisFuture.completedFuture(0L));
when(asyncCommands.get(any())).thenReturn(MockRedisFuture.completedFuture(null));
when(asyncCommands.setex(any(), anyLong(), any())).thenReturn(MockRedisFuture.completedFuture("OK"));

View File

@ -679,7 +679,7 @@ class MessagesCacheTest {
pages.add(generatePage());
pages.add(generateStaleEphemeralPage());
when(reactiveCommands.evalsha(any(), any(), any(), any()))
when(reactiveCommands.evalsha(any(), any(), any(byte[][].class), any(byte[][].class)))
.thenReturn(Flux.just(pages.pop()))
.thenReturn(Flux.just(pages.pop()))
.thenReturn(Flux.just(pages.pop()))
@ -688,7 +688,7 @@ class MessagesCacheTest {
final AsyncCommand<?, ?, ?> removeSuccess = new AsyncCommand<>(mock(RedisCommand.class));
removeSuccess.complete();
when(asyncCommands.evalsha(any(), any(), any(), any()))
when(asyncCommands.evalsha(any(), any(), any(byte[][].class), any(byte[][].class)))
.thenReturn((RedisFuture) removeSuccess);
final Publisher<?> allMessages = messagesCache.get(UUID.randomUUID(), Device.PRIMARY_ID);
@ -696,9 +696,9 @@ class MessagesCacheTest {
StepVerifier.setDefaultTimeout(Duration.ofSeconds(5));
// async commands are used for remove(), and nothing should happen until we are subscribed
verify(asyncCommands, never()).evalsha(any(), any(), any(byte[][].class), any(byte[].class));
verify(asyncCommands, never()).evalsha(any(), any(), any(byte[][].class), any(byte[][].class));
// the reactive commands will be called once, to prep the first page fetch (but no remote request would actually be sent)
verify(reactiveCommands, times(1)).evalsha(any(), any(), any(byte[][].class), any(byte[].class));
verify(reactiveCommands, times(1)).evalsha(any(), any(), any(byte[][].class), any(byte[][].class));
StepVerifier.create(allMessages)
.expectSubscription()
@ -708,7 +708,7 @@ class MessagesCacheTest {
.verify();
assertTrue(pages.isEmpty());
verify(asyncCommands, atLeast(1)).evalsha(any(), any(), any(), any());
verify(asyncCommands, atLeast(1)).evalsha(any(), any(), any(byte[][].class), any(byte[][].class));
}
private List<byte[]> generatePage() {

View File

@ -5,12 +5,11 @@
package org.whispersystems.textsecuregcm.tests.util;
import static io.dropwizard.testing.FixtureHelpers.fixture;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import io.dropwizard.util.Resources;
import org.whispersystems.textsecuregcm.util.SystemMapper;
public class JsonHelpers {
@ -26,6 +25,7 @@ public class JsonHelpers {
}
public static String jsonFixture(String filename) throws IOException {
return objectMapper.writeValueAsString(objectMapper.readValue(fixture(filename), JsonNode.class));
return objectMapper.writeValueAsString(
objectMapper.readValue(Resources.getResource(filename), JsonNode.class));
}
}

View File

@ -50,24 +50,6 @@ public class RedisClusterHelper {
return null;
}).when(cluster).useCluster(any(Consumer.class));
when(cluster.withCluster(any(Function.class))).thenAnswer(invocation -> {
return invocation.getArgument(0, Function.class).apply(stringConnection);
});
doAnswer(invocation -> {
invocation.getArgument(0, Consumer.class).accept(stringConnection);
return null;
}).when(cluster).useCluster(any(Consumer.class));
when(cluster.withBinaryCluster(any(Function.class))).thenAnswer(invocation -> {
return invocation.getArgument(0, Function.class).apply(binaryConnection);
});
doAnswer(invocation -> {
invocation.getArgument(0, Consumer.class).accept(binaryConnection);
return null;
}).when(cluster).useBinaryCluster(any(Consumer.class));
when(cluster.withBinaryCluster(any(Function.class))).thenAnswer(invocation -> {
return invocation.getArgument(0, Function.class).apply(binaryConnection);
});

View File

@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.util.logging;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@ -20,8 +21,10 @@ import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
import io.dropwizard.testing.junit5.ResourceExtension;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.Principal;
import java.time.Duration;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -40,6 +43,7 @@ import javax.ws.rs.core.Response;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.WriteCallback;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
@ -159,7 +163,7 @@ class LoggingUnhandledExceptionMapperTest {
}
private WebSocketResourceProvider<TestPrincipal> createWebsocketProvider(final String userAgentHeader,
final Session session, final Consumer<ByteBuffer> responseHandler) {
final Session session, final Consumer<ByteBuffer> responseHandler) throws IOException {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(exceptionMapper);
resourceConfig.register(new TestController());
@ -170,14 +174,14 @@ class LoggingUnhandledExceptionMapperTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
when(remoteEndpoint.sendBytesByFuture(any()))
.thenAnswer(answer -> {
responseHandler.accept(answer.getArgument(0, ByteBuffer.class));
return CompletableFuture.completedFuture(null);
});
doAnswer(answer -> {
responseHandler.accept(answer.getArgument(0, ByteBuffer.class));
return null;
}).when(remoteEndpoint).sendBytes(any(), any(WriteCallback.class));
UpgradeRequest request = mock(UpgradeRequest.class);
when(session.getUpgradeRequest()).thenReturn(request);

View File

@ -13,12 +13,11 @@
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-api</artifactId>
<artifactId>websocket-jetty-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<scope>runtime</scope>
<artifactId>websocket-jetty-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
@ -97,11 +96,6 @@
<artifactId>jsr305</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>

View File

@ -14,7 +14,7 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.exceptions.WebSocketException;
import org.eclipse.jetty.websocket.api.WriteCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -99,7 +99,7 @@ public class WebSocketClient {
public void hardDisconnectQuietly() {
try {
session.disconnect();
} catch (IOException e) {
} catch (Exception e) {
// quietly we said
}
}

View File

@ -7,10 +7,28 @@ package org.whispersystems.websocket;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.net.HttpHeaders;
import com.google.protobuf.UninitializedMessageException;
import org.eclipse.jetty.websocket.api.MessageTooLargeException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.security.Principal;
import java.time.Duration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.api.WriteCallback;
import org.eclipse.jetty.websocket.api.exceptions.MessageTooLargeException;
import org.glassfish.jersey.internal.MapPropertiesDelegate;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ContainerRequest;
@ -27,23 +45,6 @@ import org.whispersystems.websocket.session.ContextPrincipal;
import org.whispersystems.websocket.session.WebSocketSessionContext;
import org.whispersystems.websocket.setup.WebSocketConnectListener;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.security.Principal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public class WebSocketResourceProvider<T extends Principal> implements WebSocketListener {
@ -57,44 +58,44 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
private final Map<Long, CompletableFuture<WebSocketResponseMessage>> requestMap = new ConcurrentHashMap<>();
private final T authenticated;
private final WebSocketMessageFactory messageFactory;
private final T authenticated;
private final WebSocketMessageFactory messageFactory;
private final Optional<WebSocketConnectListener> connectListener;
private final ApplicationHandler jerseyHandler;
private final WebsocketRequestLog requestLog;
private final long idleTimeoutMillis;
private final String remoteAddress;
private final ApplicationHandler jerseyHandler;
private final WebsocketRequestLog requestLog;
private final Duration idleTimeout;
private final String remoteAddress;
private Session session;
private RemoteEndpoint remoteEndpoint;
private Session session;
private RemoteEndpoint remoteEndpoint;
private WebSocketSessionContext context;
private static final Set<String> EXCLUDED_UPGRADE_REQUEST_HEADERS = Set.of("connection", "upgrade");
public WebSocketResourceProvider(String remoteAddress,
ApplicationHandler jerseyHandler,
WebsocketRequestLog requestLog,
T authenticated,
WebSocketMessageFactory messageFactory,
Optional<WebSocketConnectListener> connectListener,
long idleTimeoutMillis)
{
this.remoteAddress = remoteAddress;
this.jerseyHandler = jerseyHandler;
this.requestLog = requestLog;
this.authenticated = authenticated;
this.messageFactory = messageFactory;
this.connectListener = connectListener;
this.idleTimeoutMillis = idleTimeoutMillis;
public WebSocketResourceProvider(String remoteAddress,
ApplicationHandler jerseyHandler,
WebsocketRequestLog requestLog,
T authenticated,
WebSocketMessageFactory messageFactory,
Optional<WebSocketConnectListener> connectListener,
Duration idleTimeout) {
this.remoteAddress = remoteAddress;
this.jerseyHandler = jerseyHandler;
this.requestLog = requestLog;
this.authenticated = authenticated;
this.messageFactory = messageFactory;
this.connectListener = connectListener;
this.idleTimeout = idleTimeout;
}
@Override
public void onWebSocketConnect(Session session) {
this.session = session;
this.session = session;
this.remoteEndpoint = session.getRemote();
this.context = new WebSocketSessionContext(new WebSocketClient(session, remoteEndpoint, messageFactory, requestMap));
this.context = new WebSocketSessionContext(
new WebSocketClient(session, remoteEndpoint, messageFactory, requestMap));
this.context.setAuthenticated(authenticated);
this.session.setIdleTimeout(idleTimeoutMillis);
this.session.setIdleTimeout(idleTimeout);
connectListener.ifPresent(listener -> listener.onWebSocketConnect(this.context));
}
@ -129,12 +130,12 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
handleResponse(webSocketMessage.getResponseMessage());
break;
default:
close(session, 1018, "Badly formatted");
close(session, 1007, "Badly formatted");
break;
}
} catch (UninitializedMessageException | InvalidMessageException e) {
logger.debug("Parsing", e);
close(session, 1018, "Badly formatted");
close(session, 1007, "Badly formatted");
}
}
@ -159,23 +160,36 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
}
private void handleRequest(WebSocketRequestMessage requestMessage) {
ContainerRequest containerRequest = new ContainerRequest(null, URI.create(requestMessage.getPath()), requestMessage.getVerb(), new WebSocketSecurityContext(new ContextPrincipal(context)), new MapPropertiesDelegate(new HashMap<>()), jerseyHandler.getConfiguration());
ContainerRequest containerRequest = new ContainerRequest(null, URI.create(requestMessage.getPath()),
requestMessage.getVerb(), new WebSocketSecurityContext(new ContextPrincipal(context)),
new MapPropertiesDelegate(new HashMap<>()), jerseyHandler.getConfiguration());
containerRequest.headers(getCombinedHeaders(session.getUpgradeRequest().getHeaders(), requestMessage.getHeaders()));
if (requestMessage.getBody().isPresent()) {
containerRequest.setEntityStream(new ByteArrayInputStream(requestMessage.getBody().get()));
}
ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
CompletableFuture<ContainerResponse> responseFuture = (CompletableFuture<ContainerResponse>) jerseyHandler.apply(containerRequest, responseBody);
ByteArrayOutputStream responseBody = new ByteArrayOutputStream();
CompletableFuture<ContainerResponse> responseFuture = (CompletableFuture<ContainerResponse>) jerseyHandler.apply(
containerRequest, responseBody);
responseFuture.thenAccept(response -> {
sendResponse(requestMessage, response, responseBody);
try {
sendResponse(requestMessage, response, responseBody);
} catch (IOException e) {
throw new RuntimeException(e);
}
requestLog.log(remoteAddress, containerRequest, response);
}).exceptionally(exception -> {
logger.warn("Websocket Error: " + requestMessage.getVerb() + " " + requestMessage.getPath() + "\n" + requestMessage.getBody(), exception);
sendErrorResponse(requestMessage, Response.status(500).build());
requestLog.log(remoteAddress, containerRequest, new ContainerResponse(containerRequest, Response.status(500).build()));
logger.warn("Websocket Error: " + requestMessage.getVerb() + " " + requestMessage.getPath() + "\n"
+ requestMessage.getBody(), exception);
try {
sendErrorResponse(requestMessage, Response.status(500).build());
} catch (IOException e) {
logger.warn("Failed to send error response", e);
}
requestLog.log(remoteAddress, containerRequest,
new ContainerResponse(containerRequest, Response.status(500).build()));
return null;
});
}
@ -217,7 +231,8 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
session.close(status, message);
}
private void sendResponse(WebSocketRequestMessage requestMessage, ContainerResponse response, ByteArrayOutputStream responseBody) {
private void sendResponse(WebSocketRequestMessage requestMessage, ContainerResponse response,
ByteArrayOutputStream responseBody) throws IOException {
if (requestMessage.hasRequestId()) {
byte[] body = responseBody.toByteArray();
@ -226,25 +241,25 @@ public class WebSocketResourceProvider<T extends Principal> implements WebSocket
}
byte[] responseBytes = messageFactory.createResponse(requestMessage.getRequestId(),
response.getStatus(),
response.getStatusInfo().getReasonPhrase(),
getHeaderList(response.getStringHeaders()),
Optional.ofNullable(body))
.toByteArray();
response.getStatus(),
response.getStatusInfo().getReasonPhrase(),
getHeaderList(response.getStringHeaders()),
Optional.ofNullable(body))
.toByteArray();
remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(responseBytes));
remoteEndpoint.sendBytes(ByteBuffer.wrap(responseBytes), WriteCallback.NOOP);
}
}
private void sendErrorResponse(WebSocketRequestMessage requestMessage, Response error) {
private void sendErrorResponse(WebSocketRequestMessage requestMessage, Response error) throws IOException {
if (requestMessage.hasRequestId()) {
WebSocketMessage response = messageFactory.createResponse(requestMessage.getRequestId(),
error.getStatus(),
"Error response",
getHeaderList(error.getStringHeaders()),
Optional.empty());
error.getStatus(),
"Error response",
getHeaderList(error.getStringHeaders()),
Optional.empty());
remoteEndpoint.sendBytesByFuture(ByteBuffer.wrap(response.toByteArray()));
remoteEndpoint.sendBytes(ByteBuffer.wrap(response.toByteArray()), WriteCallback.NOOP);
}
}

View File

@ -9,14 +9,15 @@ import static java.util.Optional.ofNullable;
import com.google.common.net.HttpHeaders;
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.Principal;
import java.util.Arrays;
import java.util.Optional;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse;
import org.eclipse.jetty.websocket.server.JettyWebSocketCreator;
import org.eclipse.jetty.websocket.server.JettyWebSocketServlet;
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
import org.glassfish.jersey.server.ApplicationHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -28,7 +29,8 @@ import org.whispersystems.websocket.configuration.WebSocketConfiguration;
import org.whispersystems.websocket.session.WebSocketSessionContextValueFactoryProvider;
import org.whispersystems.websocket.setup.WebSocketEnvironment;
public class WebSocketResourceProviderFactory<T extends Principal> extends WebSocketServlet implements WebSocketCreator {
public class WebSocketResourceProviderFactory<T extends Principal> extends JettyWebSocketServlet implements
JettyWebSocketCreator {
private static final Logger logger = LoggerFactory.getLogger(WebSocketResourceProviderFactory.class);
@ -50,10 +52,10 @@ public class WebSocketResourceProviderFactory<T extends Principal> extends WebSo
}
@Override
public Object createWebSocket(ServletUpgradeRequest request, ServletUpgradeResponse response) {
public Object createWebSocket(final JettyServerUpgradeRequest request, final JettyServerUpgradeResponse response) {
try {
Optional<WebSocketAuthenticator<T>> authenticator = Optional.ofNullable(environment.getAuthenticator());
T authenticated = null;
T authenticated = null;
if (authenticator.isPresent()) {
AuthenticationResult<T> authenticationResult = authenticator.get().authenticate(request);
@ -72,7 +74,7 @@ public class WebSocketResourceProviderFactory<T extends Principal> extends WebSo
authenticated,
this.environment.getMessageFactory(),
ofNullable(this.environment.getConnectListener()),
this.environment.getIdleTimeoutMillis());
this.environment.getIdleTimeout());
} catch (AuthenticationException | IOException e) {
logger.warn("Authentication failure", e);
try {
@ -84,20 +86,23 @@ public class WebSocketResourceProviderFactory<T extends Principal> extends WebSo
}
@Override
public void configure(WebSocketServletFactory factory) {
public void configure(JettyWebSocketServletFactory factory) {
factory.setCreator(this);
factory.getPolicy().setMaxBinaryMessageSize(configuration.getMaxBinaryMessageSize());
factory.getPolicy().setMaxTextMessageSize(configuration.getMaxTextMessageSize());
factory.setMaxBinaryMessageSize(configuration.getMaxBinaryMessageSize());
factory.setMaxTextMessageSize(configuration.getMaxTextMessageSize());
}
private String getRemoteAddress(ServletUpgradeRequest request) {
private String getRemoteAddress(JettyServerUpgradeRequest request) {
String forwardedFor = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
if (forwardedFor == null || forwardedFor.isBlank()) {
return request.getRemoteAddress();
if (request.getRemoteSocketAddress() instanceof InetSocketAddress inetSocketAddress) {
return inetSocketAddress.getAddress().getHostAddress();
}
return null;
} else {
return Arrays.stream(forwardedFor.split(","))
.map(String::trim)
.map(String::trim)
.reduce((a, b) -> b)
.orElseThrow();
}

View File

@ -9,6 +9,7 @@ import java.util.Optional;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
public interface WebSocketAuthenticator<T extends Principal> {
AuthenticationResult<T> authenticate(UpgradeRequest request) throws AuthenticationException;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")

View File

@ -5,7 +5,7 @@
package org.whispersystems.websocket.logging;
import ch.qos.logback.core.AsyncAppenderBase;
import io.dropwizard.logging.async.AsyncAppenderFactory;
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
public class AsyncWebsocketEventAppenderFactory implements AsyncAppenderFactory<WebsocketEvent> {
@Override

View File

@ -15,12 +15,12 @@ import java.util.List;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import io.dropwizard.logging.AppenderFactory;
import io.dropwizard.logging.ConsoleAppenderFactory;
import io.dropwizard.logging.async.AsyncAppenderFactory;
import io.dropwizard.logging.filter.LevelFilterFactory;
import io.dropwizard.logging.filter.NullLevelFilterFactory;
import io.dropwizard.logging.layout.LayoutFactory;
import io.dropwizard.logging.common.AppenderFactory;
import io.dropwizard.logging.common.ConsoleAppenderFactory;
import io.dropwizard.logging.common.async.AsyncAppenderFactory;
import io.dropwizard.logging.common.filter.LevelFilterFactory;
import io.dropwizard.logging.common.filter.NullLevelFilterFactory;
import io.dropwizard.logging.common.layout.LayoutFactory;
public class WebsocketRequestLoggerFactory {

View File

@ -6,7 +6,7 @@ package org.whispersystems.websocket.logging.layout;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.pattern.PatternLayoutBase;
import io.dropwizard.logging.layout.LayoutFactory;
import io.dropwizard.logging.common.layout.LayoutFactory;
import org.whispersystems.websocket.logging.WebsocketEvent;
import java.util.TimeZone;

View File

@ -6,10 +6,10 @@ package org.whispersystems.websocket.logging.layout.converters;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.util.CachingDateFormatter;
import org.whispersystems.websocket.logging.WebsocketEvent;
import java.time.ZoneId;
import java.util.List;
import java.util.TimeZone;
import java.util.Optional;
import org.whispersystems.websocket.logging.WebsocketEvent;
public class DateConverter extends WebSocketEventConverter {
@ -28,7 +28,15 @@ public class DateConverter extends WebSocketEventConverter {
}
try {
cachingDateFormatter = new CachingDateFormatter(datePattern);
List<String> optionList = getOptionList();
Optional<ZoneId> timeZone = Optional.empty();
// if the option list contains a TZ option, then set it.
if (optionList != null && optionList.size() > 1) {
timeZone = Optional.of(ZoneId.of((String) optionList.get(1)));
}
cachingDateFormatter = new CachingDateFormatter(datePattern, timeZone.orElse(null));
// maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern);
} catch (IllegalArgumentException e) {
addWarn("Could not instantiate SimpleDateFormat with pattern " + datePattern, e);
@ -36,13 +44,7 @@ public class DateConverter extends WebSocketEventConverter {
cachingDateFormatter = new CachingDateFormatter(CoreConstants.CLF_DATE_PATTERN);
}
List optionList = getOptionList();
// if the option list contains a TZ option, then set it.
if (optionList != null && optionList.size() > 1) {
TimeZone tz = TimeZone.getTimeZone((String) optionList.get(1));
cachingDateFormatter.setTimeZone(tz);
}
}
@Override

View File

@ -6,7 +6,8 @@ package org.whispersystems.websocket.setup;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.setup.Environment;
import io.dropwizard.core.setup.Environment;
import java.time.Duration;
import org.glassfish.jersey.server.ResourceConfig;
import org.whispersystems.websocket.auth.WebSocketAuthenticator;
import org.whispersystems.websocket.configuration.WebSocketConfiguration;
@ -19,31 +20,31 @@ import java.security.Principal;
public class WebSocketEnvironment<T extends Principal> {
private final ResourceConfig jerseyConfig;
private final ObjectMapper objectMapper;
private final Validator validator;
private final WebsocketRequestLog requestLog;
private final long idleTimeoutMillis;
private final ResourceConfig jerseyConfig;
private final ObjectMapper objectMapper;
private final Validator validator;
private final WebsocketRequestLog requestLog;
private final Duration idleTimeout;
private WebSocketAuthenticator<T> authenticator;
private WebSocketMessageFactory messageFactory;
private WebSocketConnectListener connectListener;
private WebSocketMessageFactory messageFactory;
private WebSocketConnectListener connectListener;
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration) {
this(environment, configuration, 60000);
this(environment, configuration, Duration.ofMillis(60000));
}
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration, long idleTimeoutMillis) {
this(environment, configuration.getRequestLog().build("websocket"), idleTimeoutMillis);
public WebSocketEnvironment(Environment environment, WebSocketConfiguration configuration, Duration idleTimeout) {
this(environment, configuration.getRequestLog().build("websocket"), idleTimeout);
}
public WebSocketEnvironment(Environment environment, WebsocketRequestLog requestLog, long idleTimeoutMillis) {
this.jerseyConfig = new DropwizardResourceConfig(environment.metrics());
this.objectMapper = environment.getObjectMapper();
this.validator = environment.getValidator();
this.requestLog = requestLog;
this.messageFactory = new ProtobufWebSocketMessageFactory();
this.idleTimeoutMillis = idleTimeoutMillis;
public WebSocketEnvironment(Environment environment, WebsocketRequestLog requestLog, Duration idleTimeout) {
this.jerseyConfig = new DropwizardResourceConfig(environment.metrics());
this.objectMapper = environment.getObjectMapper();
this.validator = environment.getValidator();
this.requestLog = requestLog;
this.messageFactory = new ProtobufWebSocketMessageFactory();
this.idleTimeout = idleTimeout;
}
public ResourceConfig jersey() {
@ -58,8 +59,8 @@ public class WebSocketEnvironment<T extends Principal> {
this.authenticator = authenticator;
}
public long getIdleTimeoutMillis() {
return idleTimeoutMillis;
public Duration getIdleTimeout() {
return idleTimeout;
}
public ObjectMapper getObjectMapper() {

View File

@ -20,10 +20,9 @@ import java.util.Optional;
import javax.security.auth.Subject;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse;
import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -37,8 +36,8 @@ public class WebSocketResourceProviderFactoryTest {
private ResourceConfig jerseyEnvironment;
private WebSocketEnvironment<Account> environment;
private WebSocketAuthenticator<Account> authenticator;
private ServletUpgradeRequest request;
private ServletUpgradeResponse response;
private JettyServerUpgradeRequest request;
private JettyServerUpgradeResponse response;
@BeforeEach
void setup() {
@ -47,8 +46,8 @@ public class WebSocketResourceProviderFactoryTest {
environment = mock(WebSocketEnvironment.class);
//noinspection unchecked
authenticator = mock(WebSocketAuthenticator.class);
request = mock(ServletUpgradeRequest.class);
response = mock(ServletUpgradeResponse.class);
request = mock(JettyServerUpgradeRequest.class);
response = mock(JettyServerUpgradeResponse.class);
}
@ -111,9 +110,8 @@ public class WebSocketResourceProviderFactoryTest {
@Test
void testConfigure() {
WebSocketServletFactory servletFactory = mock(WebSocketServletFactory.class);
JettyWebSocketServletFactory servletFactory = mock(JettyWebSocketServletFactory.class);
when(environment.jersey()).thenReturn(jerseyEnvironment);
when(servletFactory.getPolicy()).thenReturn(mock(WebSocketPolicy.class));
WebSocketResourceProviderFactory<Account> factory = new WebSocketResourceProviderFactory<>(environment,
Account.class,

View File

@ -11,21 +11,21 @@ import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.net.HttpHeaders;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import io.dropwizard.auth.Auth;
import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.security.Principal;
import java.time.Duration;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@ -80,7 +80,7 @@ class WebSocketResourceProviderTest {
new TestPrincipal("fooz"),
new ProtobufWebSocketMessageFactory(),
Optional.of(connectListener),
30000);
Duration.ofMillis(30000));
Session session = mock(Session.class);
UpgradeRequest request = mock(UpgradeRequest.class);
@ -105,7 +105,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = mock(ApplicationHandler.class);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -164,7 +165,7 @@ class WebSocketResourceProviderTest {
assertThat(bundledRequest.getPath(false)).isEqualTo("bar");
verify(requestLog).log(eq("127.0.0.1"), eq(bundledRequest), eq(response));
verify(remoteEndpoint).sendBytesByFuture(responseCaptor.capture());
verify(remoteEndpoint).sendBytes(responseCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom(
responseCaptor.getValue().array());
@ -180,7 +181,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = mock(ApplicationHandler.class);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -215,7 +217,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseCaptor.capture());
verify(remoteEndpoint).sendBytes(responseCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketMessage responseMessageContainer = SubProtocol.WebSocketMessage.parseFrom(
responseCaptor.getValue().array());
@ -225,7 +227,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageSuccess() throws InvalidProtocolBufferException {
void testActualRouteMessageSuccess() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -235,7 +237,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -253,7 +256,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -264,7 +267,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageNotFound() throws InvalidProtocolBufferException {
void testActualRouteMessageNotFound() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -274,7 +277,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("foo"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -292,7 +296,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -303,7 +307,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageAuthorized() throws InvalidProtocolBufferException {
void testActualRouteMessageAuthorized() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -314,7 +318,7 @@ class WebSocketResourceProviderTest {
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("authorizedUserName"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
30000);
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -332,7 +336,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -343,7 +347,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageUnauthorized() throws InvalidProtocolBufferException {
void testActualRouteMessageUnauthorized() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -353,7 +357,7 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -371,7 +375,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -381,7 +385,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageOptionalAuthorizedPresent() throws InvalidProtocolBufferException {
void testActualRouteMessageOptionalAuthorizedPresent() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -391,7 +395,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("something"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("something"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -409,7 +414,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -420,7 +425,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageOptionalAuthorizedEmpty() throws InvalidProtocolBufferException {
void testActualRouteMessageOptionalAuthorizedEmpty() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -430,7 +435,7 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, null, new ProtobufWebSocketMessageFactory(), Optional.empty(), Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -448,7 +453,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -459,7 +464,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessagePutAuthenticatedEntity() throws InvalidProtocolBufferException, JsonProcessingException {
void testActualRouteMessagePutAuthenticatedEntity() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -469,7 +474,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -488,7 +494,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -499,8 +505,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessagePutAuthenticatedBadEntity()
throws InvalidProtocolBufferException, JsonProcessingException {
void testActualRouteMessagePutAuthenticatedBadEntity() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new WebSocketSessionContextValueFactoryProvider.Binder());
@ -510,7 +515,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -529,7 +535,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -540,7 +546,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteMessageExceptionMapping() throws InvalidProtocolBufferException {
void testActualRouteMessageExceptionMapping() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new TestExceptionMapper());
@ -551,7 +557,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -569,7 +576,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -579,7 +586,7 @@ class WebSocketResourceProviderTest {
}
@Test
void testActualRouteSessionContextInjection() throws InvalidProtocolBufferException {
void testActualRouteSessionContextInjection() throws Exception {
ResourceConfig resourceConfig = new DropwizardResourceConfig();
resourceConfig.register(new TestResource());
resourceConfig.register(new TestExceptionMapper());
@ -590,7 +597,8 @@ class WebSocketResourceProviderTest {
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
WebsocketRequestLog requestLog = mock(WebsocketRequestLog.class);
WebSocketResourceProvider<TestPrincipal> provider = new WebSocketResourceProvider<>("127.0.0.1", applicationHandler,
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
requestLog, new TestPrincipal("gooduser"), new ProtobufWebSocketMessageFactory(), Optional.empty(),
Duration.ofMillis(30000));
Session session = mock(Session.class);
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
@ -622,7 +630,7 @@ class WebSocketResourceProviderTest {
ArgumentCaptor<ByteBuffer> responseBytesCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(remoteEndpoint).sendBytesByFuture(responseBytesCaptor.capture());
verify(remoteEndpoint, times(2)).sendBytes(responseBytesCaptor.capture(), any(WriteCallback.class));
SubProtocol.WebSocketResponseMessage response = getResponse(responseBytesCaptor);
@ -690,12 +698,12 @@ class WebSocketResourceProviderTest {
}
private SubProtocol.WebSocketResponseMessage getResponse(ArgumentCaptor<ByteBuffer> responseCaptor)
throws InvalidProtocolBufferException {
throws Exception {
return SubProtocol.WebSocketMessage.parseFrom(responseCaptor.getValue().array()).getResponse();
}
private SubProtocol.WebSocketRequestMessage getRequest(ArgumentCaptor<ByteBuffer> requestCaptor)
throws InvalidProtocolBufferException {
throws Exception {
return SubProtocol.WebSocketMessage.parseFrom(requestCaptor.getValue().array()).getRequest();
}

View File

@ -11,7 +11,7 @@ import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.OutputStreamAppender;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import com.google.common.net.HttpHeaders;
import io.dropwizard.logging.AbstractOutputStreamAppenderFactory;
import io.dropwizard.logging.common.AbstractOutputStreamAppenderFactory;
import java.io.ByteArrayOutputStream;
import java.net.URI;
import java.util.ArrayList;