mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-22 18:37:58 +01:00
Migrate to 429 for all ratelimit responses
This commit is contained in:
@@ -7,7 +7,7 @@ package org.whispersystems.textsecuregcm.auth;
|
||||
|
||||
public enum RegistrationLockError {
|
||||
MISMATCH(RegistrationLockVerificationManager.FAILURE_HTTP_STATUS),
|
||||
RATE_LIMITED(413) // This will be changed to 429 in a future revision
|
||||
RATE_LIMITED(429)
|
||||
;
|
||||
|
||||
private final int expectedStatus;
|
||||
|
||||
@@ -409,7 +409,6 @@ public class BackupAuthManagerTest {
|
||||
final RateLimitExceededException ex = CompletableFutureTestUtil.assertFailsWithCause(
|
||||
RateLimitExceededException.class,
|
||||
authManager.commitBackupId(account, credentialRequest));
|
||||
assertThat(ex.isLegacy()).isFalse();
|
||||
|
||||
// If we don't change the request, shouldn't be rate limited
|
||||
when(account.getBackupCredentialRequest()).thenReturn(credentialRequest.serialize());
|
||||
@@ -436,7 +435,7 @@ public class BackupAuthManagerTest {
|
||||
final RateLimiters limiters = mock(RateLimiters.class);
|
||||
final RateLimiter limiter = mock(RateLimiter.class);
|
||||
when(limiter.validateAsync(aci))
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null, false)));
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null)));
|
||||
when(limiters.forDescriptor(RateLimiters.For.SET_BACKUP_ID)).thenReturn(limiter);
|
||||
return limiters;
|
||||
}
|
||||
|
||||
@@ -151,11 +151,10 @@ public class BackupManagerTest {
|
||||
public void createTemporaryMediaAttachmentRateLimited() {
|
||||
final AuthenticatedBackupUser backupUser = backupUser(TestRandomUtil.nextBytes(16), BackupLevel.MEDIA);
|
||||
when(mediaUploadLimiter.validateAsync(eq(BackupManager.rateLimitKey(backupUser))))
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null, true)));
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null)));
|
||||
final RateLimitExceededException e = CompletableFutureTestUtil.assertFailsWithCause(
|
||||
RateLimitExceededException.class,
|
||||
backupManager.createTemporaryAttachmentUploadDescriptor(backupUser).toCompletableFuture());
|
||||
assertThat(e.isLegacy()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -912,7 +912,7 @@ class AccountControllerTest {
|
||||
.request()
|
||||
.head()) {
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(413);
|
||||
assertThat(response.getStatus()).isEqualTo(429);
|
||||
assertThat(response.getHeaderString("Retry-After")).isEqualTo(String.valueOf(expectedRetryAfter.toSeconds()));
|
||||
}
|
||||
}
|
||||
@@ -963,7 +963,7 @@ class AccountControllerTest {
|
||||
.request()
|
||||
.get();
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(413);
|
||||
assertThat(response.getStatus()).isEqualTo(429);
|
||||
assertThat(response.getHeaderString("Retry-After")).isEqualTo(String.valueOf(expectedRetryAfter.toSeconds()));
|
||||
}
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ class AccountControllerV2Test {
|
||||
|
||||
@Test
|
||||
void rateLimitedNumber() throws Exception {
|
||||
doThrow(new RateLimitExceededException(null, true))
|
||||
doThrow(new RateLimitExceededException(null))
|
||||
.when(registrationLimiter).validate(anyString());
|
||||
|
||||
final Invocation.Builder request = resources.getJerseyTest()
|
||||
@@ -364,7 +364,7 @@ class AccountControllerV2Test {
|
||||
|
||||
final Exception e = switch (error) {
|
||||
case MISMATCH -> new WebApplicationException(error.getExpectedStatus());
|
||||
case RATE_LIMITED -> new RateLimitExceededException(null, true);
|
||||
case RATE_LIMITED -> new RateLimitExceededException(null);
|
||||
};
|
||||
doThrow(e)
|
||||
.when(registrationLockVerificationManager).verifyRegistrationLock(any(), any(), any(), any(), any());
|
||||
|
||||
@@ -252,7 +252,7 @@ public class ArchiveControllerTest {
|
||||
|
||||
public static Stream<Arguments> setBackupIdException() {
|
||||
return Stream.of(
|
||||
Arguments.of(new RateLimitExceededException(null, false), false, 429),
|
||||
Arguments.of(new RateLimitExceededException(null), false, 429),
|
||||
Arguments.of(Status.INVALID_ARGUMENT.withDescription("async").asRuntimeException(), false, 400),
|
||||
Arguments.of(Status.INVALID_ARGUMENT.withDescription("sync").asRuntimeException(), true, 400)
|
||||
);
|
||||
@@ -529,7 +529,7 @@ public class ArchiveControllerTest {
|
||||
|
||||
// rate limit
|
||||
when(backupManager.createTemporaryAttachmentUploadDescriptor(any()))
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null, false)));
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null)));
|
||||
final Response response = resources.getJerseyTest()
|
||||
.target("v1/archives/media/upload/form")
|
||||
.request()
|
||||
|
||||
@@ -122,7 +122,7 @@ public class CallLinkControllerTest {
|
||||
|
||||
@Test
|
||||
void testGetCreateAuthRatelimited() throws RateLimitExceededException{
|
||||
doThrow(new RateLimitExceededException(null, false))
|
||||
doThrow(new RateLimitExceededException(null))
|
||||
.when(createCallLinkLimiter).validate(AuthHelper.VALID_UUID);
|
||||
|
||||
try (Response response = resources.getJerseyTest()
|
||||
|
||||
@@ -170,7 +170,7 @@ class CallRoutingControllerTest {
|
||||
|
||||
@Test
|
||||
void testGetTurnEndpointRateLimited() throws RateLimitExceededException {
|
||||
doThrow(new RateLimitExceededException(null, false))
|
||||
doThrow(new RateLimitExceededException(null))
|
||||
.when(getCallEndpointLimiter).validate(AuthHelper.VALID_UUID);
|
||||
|
||||
try (final Response response = resources.getJerseyTest()
|
||||
|
||||
@@ -100,7 +100,7 @@ class ChallengeControllerTest {
|
||||
""";
|
||||
|
||||
final Duration retryAfter = Duration.ofMinutes(17);
|
||||
doThrow(new RateLimitExceededException(retryAfter, true)).when(rateLimitChallengeManager)
|
||||
doThrow(new RateLimitExceededException(retryAfter)).when(rateLimitChallengeManager)
|
||||
.answerPushChallenge(any(), any());
|
||||
|
||||
final Response response = EXTENSION.target("/v1/challenge")
|
||||
@@ -108,7 +108,7 @@ class ChallengeControllerTest {
|
||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||
.put(Entity.json(pushChallengeJson));
|
||||
|
||||
assertEquals(413, response.getStatus());
|
||||
assertEquals(429, response.getStatus());
|
||||
assertEquals(String.valueOf(retryAfter.toSeconds()), response.getHeaderString("Retry-After"));
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ class ChallengeControllerTest {
|
||||
""";
|
||||
|
||||
final Duration retryAfter = Duration.ofMinutes(17);
|
||||
doThrow(new RateLimitExceededException(retryAfter, true)).when(rateLimitChallengeManager)
|
||||
doThrow(new RateLimitExceededException(retryAfter)).when(rateLimitChallengeManager)
|
||||
.answerCaptchaChallenge(any(), any(), any(), any(), any());
|
||||
|
||||
final Response response = EXTENSION.target("/v1/challenge")
|
||||
@@ -183,7 +183,7 @@ class ChallengeControllerTest {
|
||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||
.put(Entity.json(captchaChallengeJson));
|
||||
|
||||
assertEquals(413, response.getStatus());
|
||||
assertEquals(429, response.getStatus());
|
||||
assertEquals(String.valueOf(retryAfter.toSeconds()), response.getHeaderString("Retry-After"));
|
||||
}
|
||||
|
||||
|
||||
@@ -462,7 +462,7 @@ class KeysControllerTest {
|
||||
@Test
|
||||
void testGetKeysRateLimited() throws RateLimitExceededException {
|
||||
Duration retryAfter = Duration.ofSeconds(31);
|
||||
doThrow(new RateLimitExceededException(retryAfter, true)).when(rateLimiter).validate(anyString());
|
||||
doThrow(new RateLimitExceededException(retryAfter)).when(rateLimiter).validate(anyString());
|
||||
|
||||
Response result = resources.getJerseyTest()
|
||||
.target(String.format("/v2/keys/PNI:%s/*", EXISTS_PNI))
|
||||
@@ -470,7 +470,7 @@ class KeysControllerTest {
|
||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||
.get();
|
||||
|
||||
assertThat(result.getStatus()).isEqualTo(413);
|
||||
assertThat(result.getStatus()).isEqualTo(429);
|
||||
assertThat(result.getHeaderString("Retry-After")).isEqualTo(String.valueOf(retryAfter.toSeconds()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1695,10 +1695,10 @@ class MessageControllerTest {
|
||||
.header(HeaderUtils.UNIDENTIFIED_ACCESS_KEY, Base64.getEncoder().encodeToString(UNIDENTIFIED_ACCESS_BYTES));
|
||||
|
||||
when(rateLimiter.validateAsync(any(UUID.class)))
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(Duration.ofSeconds(77), true)));
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(Duration.ofSeconds(77))));
|
||||
|
||||
try (final Response response = invocationBuilder.put(entity)) {
|
||||
assertEquals(413, response.getStatus());
|
||||
assertEquals(429, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ class ProfileControllerTest {
|
||||
|
||||
@Test
|
||||
void testProfileGetByAciRateLimited() throws RateLimitExceededException {
|
||||
doThrow(new RateLimitExceededException(Duration.ofSeconds(13), true)).when(rateLimiter)
|
||||
doThrow(new RateLimitExceededException(Duration.ofSeconds(13))).when(rateLimiter)
|
||||
.validate(AuthHelper.VALID_UUID);
|
||||
|
||||
final Response response = resources.getJerseyTest()
|
||||
@@ -272,7 +272,7 @@ class ProfileControllerTest {
|
||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||
.get();
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(413);
|
||||
assertThat(response.getStatus()).isEqualTo(429);
|
||||
assertThat(response.getHeaderString("Retry-After")).isEqualTo(String.valueOf(Duration.ofSeconds(13).toSeconds()));
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ class ProfileControllerTest {
|
||||
|
||||
@Test
|
||||
void testProfileGetByPniRateLimited() throws RateLimitExceededException {
|
||||
doThrow(new RateLimitExceededException(Duration.ofSeconds(13), true)).when(rateLimiter)
|
||||
doThrow(new RateLimitExceededException(Duration.ofSeconds(13))).when(rateLimiter)
|
||||
.validate(AuthHelper.VALID_UUID);
|
||||
|
||||
final Response response = resources.getJerseyTest()
|
||||
@@ -401,7 +401,7 @@ class ProfileControllerTest {
|
||||
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
|
||||
.get();
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(413);
|
||||
assertThat(response.getStatus()).isEqualTo(429);
|
||||
assertThat(response.getHeaderString("Retry-After")).isEqualTo(String.valueOf(Duration.ofSeconds(13).toSeconds()));
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ class ProvisioningControllerTest {
|
||||
final String destination = UUID.randomUUID().toString();
|
||||
final byte[] messageBody = "test".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
doThrow(new RateLimitExceededException(Duration.ZERO, true))
|
||||
doThrow(new RateLimitExceededException(Duration.ZERO))
|
||||
.when(messagesRateLimiter).validate(AuthHelper.VALID_UUID);
|
||||
|
||||
try (final Response response = RESOURCE_EXTENSION.getJerseyTest()
|
||||
@@ -111,7 +111,7 @@ class ProvisioningControllerTest {
|
||||
.put(Entity.entity(new ProvisioningMessage(Base64.getMimeEncoder().encodeToString(messageBody)),
|
||||
MediaType.APPLICATION_JSON))) {
|
||||
|
||||
assertEquals(413, response.getStatus());
|
||||
assertEquals(429, response.getStatus());
|
||||
|
||||
verify(provisioningManager, never()).sendProvisioningMessage(any(), any());
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ class RegistrationControllerTest {
|
||||
} else if (error != null) {
|
||||
final Exception e = switch (error) {
|
||||
case MISMATCH -> new WebApplicationException(error.getExpectedStatus());
|
||||
case RATE_LIMITED -> new RateLimitExceededException(null, true);
|
||||
case RATE_LIMITED -> new RateLimitExceededException(null);
|
||||
};
|
||||
doThrow(e)
|
||||
.when(registrationLockVerificationManager).verifyRegistrationLock(any(), any(), any(), any(), any());
|
||||
|
||||
@@ -180,7 +180,7 @@ class VerificationControllerTest {
|
||||
@Test
|
||||
void createSessionRateLimited() {
|
||||
when(registrationServiceClient.createRegistrationSession(any(), anyBoolean(), any()))
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null, true)));
|
||||
.thenReturn(CompletableFuture.failedFuture(new RateLimitExceededException(null)));
|
||||
|
||||
final Invocation.Builder request = resources.getJerseyTest()
|
||||
.target("/v1/verification/session")
|
||||
|
||||
@@ -121,7 +121,7 @@ class AccountsAnonymousGrpcServiceTest extends
|
||||
final Duration retryAfter = Duration.ofSeconds(11);
|
||||
|
||||
when(rateLimiter.validateReactive(anyString()))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter)));
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
GrpcTestUtils.assertRateLimitExceeded(retryAfter,
|
||||
@@ -186,7 +186,7 @@ class AccountsAnonymousGrpcServiceTest extends
|
||||
final Duration retryAfter = Duration.ofSeconds(13);
|
||||
|
||||
when(rateLimiter.validateReactive(anyString()))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter)));
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
GrpcTestUtils.assertRateLimitExceeded(retryAfter,
|
||||
@@ -254,7 +254,7 @@ class AccountsAnonymousGrpcServiceTest extends
|
||||
final Duration retryAfter = Duration.ofSeconds(17);
|
||||
|
||||
when(rateLimiter.validateReactive(anyString()))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter)));
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
GrpcTestUtils.assertRateLimitExceeded(retryAfter,
|
||||
|
||||
@@ -342,7 +342,7 @@ class AccountsGrpcServiceTest extends SimpleBaseGrpcTest<AccountsGrpcService, Ac
|
||||
final Duration retryAfter = Duration.ofMinutes(3);
|
||||
|
||||
when(rateLimiter.validateReactive(any(UUID.class)))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter)));
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
GrpcTestUtils.assertRateLimitExceeded(retryAfter,
|
||||
@@ -577,7 +577,7 @@ class AccountsGrpcServiceTest extends SimpleBaseGrpcTest<AccountsGrpcService, Ac
|
||||
final Duration retryAfter = Duration.ofSeconds(97);
|
||||
|
||||
when(rateLimiter.validateReactive(any(UUID.class)))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter)));
|
||||
|
||||
final byte[] usernameCiphertext = TestRandomUtil.nextBytes(EncryptedUsername.MAX_SIZE);
|
||||
|
||||
@@ -607,7 +607,7 @@ class AccountsGrpcServiceTest extends SimpleBaseGrpcTest<AccountsGrpcService, Ac
|
||||
final Duration retryAfter = Duration.ofSeconds(11);
|
||||
|
||||
when(rateLimiter.validateReactive(any(UUID.class)))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfter)));
|
||||
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
GrpcTestUtils.assertRateLimitExceeded(retryAfter,
|
||||
|
||||
@@ -628,7 +628,7 @@ class KeysGrpcServiceTest extends SimpleBaseGrpcTest<KeysGrpcService, KeysGrpc.K
|
||||
|
||||
final Duration retryAfterDuration = Duration.ofMinutes(7);
|
||||
when(preKeysRateLimiter.validateReactive(anyString()))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfterDuration, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfterDuration)));
|
||||
|
||||
assertRateLimitExceeded(retryAfterDuration, () -> authenticatedServiceStub().getPreKeys(GetPreKeysRequest.newBuilder()
|
||||
.setTargetIdentifier(ServiceIdentifier.newBuilder()
|
||||
|
||||
@@ -477,7 +477,7 @@ public class ProfileGrpcServiceTest extends SimpleBaseGrpcTest<ProfileGrpcServic
|
||||
final Duration retryAfterDuration = Duration.ofMinutes(7);
|
||||
when(accountsManager.getByServiceIdentifierAsync(any())).thenReturn(CompletableFuture.completedFuture(Optional.of(account)));
|
||||
when(rateLimiter.validateReactive(any(UUID.class)))
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfterDuration, false)));
|
||||
.thenReturn(Mono.error(new RateLimitExceededException(retryAfterDuration)));
|
||||
|
||||
final GetUnversionedProfileRequest request = GetUnversionedProfileRequest.newBuilder()
|
||||
.setServiceIdentifier(ServiceIdentifier.newBuilder()
|
||||
|
||||
@@ -69,11 +69,11 @@ public class RateLimitedByIpTest {
|
||||
public void testRateLimits() throws Exception {
|
||||
doNothing().when(RATE_LIMITER).validate(eq(IP));
|
||||
validateSuccess("/test/strict");
|
||||
doThrow(new RateLimitExceededException(RETRY_AFTER, true)).when(RATE_LIMITER).validate(eq(IP));
|
||||
doThrow(new RateLimitExceededException(RETRY_AFTER)).when(RATE_LIMITER).validate(eq(IP));
|
||||
validateFailure("/test/strict", RETRY_AFTER);
|
||||
doNothing().when(RATE_LIMITER).validate(eq(IP));
|
||||
validateSuccess("/test/strict");
|
||||
doThrow(new RateLimitExceededException(RETRY_AFTER, true)).when(RATE_LIMITER).validate(eq(IP));
|
||||
doThrow(new RateLimitExceededException(RETRY_AFTER)).when(RATE_LIMITER).validate(eq(IP));
|
||||
validateFailure("/test/strict", RETRY_AFTER);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class RateLimitedByIpTest {
|
||||
.request()
|
||||
.get();
|
||||
|
||||
assertEquals(413, response.getStatus());
|
||||
assertEquals(429, response.getStatus());
|
||||
assertEquals("" + expectedRetryAfter.getSeconds(), response.getHeaderString(HttpHeaders.RETRY_AFTER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public final class MockUtils {
|
||||
final Duration retryAfter,
|
||||
final boolean legacyStatusCode) {
|
||||
try {
|
||||
final RateLimitExceededException exception = new RateLimitExceededException(retryAfter, legacyStatusCode);
|
||||
final RateLimitExceededException exception = new RateLimitExceededException(retryAfter);
|
||||
doThrow(exception).when(mockRateLimiter).validate(eq(input));
|
||||
doReturn(CompletableFuture.failedFuture(exception)).when(mockRateLimiter).validateAsync(eq(input));
|
||||
doReturn(Mono.fromFuture(CompletableFuture.failedFuture(exception))).when(mockRateLimiter).validateReactive(eq(input));
|
||||
@@ -117,7 +117,7 @@ public final class MockUtils {
|
||||
final Duration retryAfter,
|
||||
final boolean legacyStatusCode) {
|
||||
try {
|
||||
final RateLimitExceededException exception = new RateLimitExceededException(retryAfter, legacyStatusCode);
|
||||
final RateLimitExceededException exception = new RateLimitExceededException(retryAfter);
|
||||
doThrow(exception).when(mockRateLimiter).validate(eq(input));
|
||||
doReturn(CompletableFuture.failedFuture(exception)).when(mockRateLimiter).validateAsync(eq(input));
|
||||
doReturn(Mono.fromFuture(CompletableFuture.failedFuture(exception))).when(mockRateLimiter).validateReactive(eq(input));
|
||||
|
||||
Reference in New Issue
Block a user