Skip to content

Commit

Permalink
Refactor HttpOpener connection handling. (#513)
Browse files Browse the repository at this point in the history
Apply connect timeout to all requests.
  • Loading branch information
blackwinter committed Dec 20, 2023
1 parent 0bddba1 commit 8621e7c
Showing 1 changed file with 51 additions and 66 deletions.
117 changes: 51 additions & 66 deletions metafacture-io/src/main/java/org/metafacture/io/HttpOpener.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,17 @@ public void process(final String input) {
final String requestUrl = getInput(input, url);
final String requestBody = getInput(input,
body == null && method.getRequestHasBody() ? INPUT_DESIGNATOR : body);
Reader reader = null;
if (requestBody != null) {
reader = doPostOrPut(requestBody, new URL(requestUrl));
}
else {
reader = doGet(requestUrl);
}
getReceiver().process(reader);

final URL urlToOpen = new URL(requestUrl);
final HttpURLConnection connection = requestBody != null ?
doOutput(urlToOpen, requestBody) : doRedirects(urlToOpen);

final InputStream inputStream = getInputStream(connection);
final String charset = getContentCharset(connection);

getReceiver().process(new InputStreamReader(
"gzip".equalsIgnoreCase(connection.getContentEncoding()) ?
new GZIPInputStream(inputStream) : inputStream, charset));
}
catch (final IOException e) {
throw new MetafactureException(e);
Expand All @@ -307,32 +310,6 @@ public void process(final String input) {
}
}

private Reader doPostOrPut(final String requestBody, final URL urlToOpen) throws IOException {
final HttpURLConnection connection = (HttpURLConnection) urlToOpen.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod(method.name());
headers.forEach(connection::setRequestProperty);
connection.getOutputStream().write(requestBody.getBytes());
final InputStream inputStream = getInputStream(connection);
return new InputStreamReader(inputStream, getContentCharset(connection));
}

private Reader doGet(final String requestUrl) throws IOException {
final Reader reader;
final HttpURLConnection connection;
connection = followRedirects(new URL(requestUrl));
final InputStream inputStream = getInputStream(connection);

if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) {
final GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
reader = new InputStreamReader(gzipInputStream, getContentCharset(connection));
}
else {
reader = new InputStreamReader(inputStream, getContentCharset(connection));
}
return reader;
}

private String getInput(final String input, final String value) {
final String result;

Expand All @@ -350,6 +327,46 @@ else if (inputUsed) {
return result;
}

private HttpURLConnection doOutput(final URL urlToOpen, final String requestBody) throws IOException {
final HttpURLConnection connection = openConnection(urlToOpen);

connection.setDoOutput(true);
connection.getOutputStream().write(requestBody.getBytes());

return connection;
}

private HttpURLConnection doRedirects(final URL startingUrl) throws IOException {
URL urlToFollow = startingUrl;

for (int i = 0; i < ALLOWED_REDIRECTIONS; ++i) {
final HttpURLConnection connection = openConnection(urlToFollow);
connection.setInstanceFollowRedirects(false); // Make the logic below easier to detect redirections

switch (connection.getResponseCode()) {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
final String location = URLDecoder.decode(connection.getHeaderField("Location"), "UTF-8");
urlToFollow = new URL(urlToFollow, location); // Deal with relative URLs
break;
default:
return connection;
}
}

throw new IOException("Too many redirects");
}

private HttpURLConnection openConnection(final URL urlToOpen) throws IOException {
final HttpURLConnection connection = (HttpURLConnection) urlToOpen.openConnection();

connection.setRequestMethod(method.name());
connection.setConnectTimeout(CONNECTION_TIMEOUT);
headers.forEach(connection::setRequestProperty);

return connection;
}

private InputStream getInputStream(final HttpURLConnection connection) throws IOException {
try {
return connection.getInputStream();
Expand Down Expand Up @@ -394,36 +411,4 @@ private String getContentCharset(final HttpURLConnection connection) {
return CHARSET_DEFAULT;
}

private HttpURLConnection followRedirects(final URL startingUrl) throws IOException {
int times = 0;
HttpURLConnection conn;
URL urlToFollow = startingUrl;
while (true) {
times = times + 1;

if (times > ALLOWED_REDIRECTIONS) {
throw new IOException("Stuck in redirect loop");
}

conn = (HttpURLConnection) urlToFollow.openConnection();
headers.forEach(conn::setRequestProperty);
conn.setRequestMethod(method.name());
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setInstanceFollowRedirects(false); // Make the logic below easier to detect redirections

switch (conn.getResponseCode()) {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
String location = conn.getHeaderField("Location");
location = URLDecoder.decode(location, "UTF-8");
urlToFollow = new URL(urlToFollow, location); // Deal with relative URLs
continue;
default:
break;
}
break;
}
return conn;
}

}

0 comments on commit 8621e7c

Please sign in to comment.