Add ICANN csv response GZIP decoding (#2269)

This commit is contained in:
Pavlo Tkach 2024-01-04 18:35:21 -05:00 committed by GitHub
parent 4eee7b8c0d
commit 5315752bc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 1 deletions

View file

@ -17,6 +17,8 @@ package google.registry.rdap;
import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK; import static com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK;
import static com.google.common.net.HttpHeaders.ACCEPT_ENCODING; import static com.google.common.net.HttpHeaders.ACCEPT_ENCODING;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.UrlConnectionUtils.gUnzipBytes;
import static google.registry.request.UrlConnectionUtils.isGZipped;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -115,7 +117,13 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
if (connection.getResponseCode() != STATUS_CODE_OK) { if (connection.getResponseCode() != STATUS_CODE_OK) {
throw new UrlConnectionException("Failed to load RDAP base URLs from ICANN", connection); throw new UrlConnectionException("Failed to load RDAP base URLs from ICANN", connection);
} }
csvString = new String(UrlConnectionUtils.getResponseBytes(connection), UTF_8); // With GZIP encoding header in the request (see above) ICANN had still sent response in plain
// text until at some point they started sending the response encoded in gzip, which broke our
// parsing of the response. Because of that it was decided to check for the response encoding,
// just in case they ever start sending a plain text again.
byte[] responseBytes = UrlConnectionUtils.getResponseBytes(connection);
csvString =
new String(isGZipped(responseBytes) ? gUnzipBytes(responseBytes) : responseBytes, UTF_8);
} finally { } finally {
connection.disconnect(); connection.disconnect();
} }

View file

@ -25,12 +25,15 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.net.MediaType; import com.google.common.net.MediaType;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.Random; import java.util.Random;
import java.util.zip.GZIPInputStream;
import org.apache.commons.compress.utils.IOUtils;
/** Utilities for common functionality relating to {@link URLConnection}s. */ /** Utilities for common functionality relating to {@link URLConnection}s. */
public final class UrlConnectionUtils { public final class UrlConnectionUtils {
@ -55,6 +58,20 @@ public final class UrlConnectionUtils {
} }
} }
/** Decodes compressed data in GZIP format. */
public static byte[] gUnzipBytes(byte[] bytes) throws IOException {
try (GZIPInputStream inputStream = new GZIPInputStream(new ByteArrayInputStream(bytes))) {
return IOUtils.toByteArray(inputStream);
}
}
/** Checks whether {@code bytes} are GZIP encoded. */
public static boolean isGZipped(byte[] bytes) {
// See GzipOutputStream.writeHeader()
return (bytes.length > 2 && bytes[0] == (byte) (GZIPInputStream.GZIP_MAGIC))
&& (bytes[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8));
}
/** Sets auth on the given connection with the given username/password. */ /** Sets auth on the given connection with the given username/password. */
public static void setBasicAuth(HttpURLConnection connection, String username, String password) { public static void setBasicAuth(HttpURLConnection connection, String username, String password) {
setBasicAuth(connection, String.format("%s:%s", username, password)); setBasicAuth(connection, String.format("%s:%s", username, password));