From 2e15ed5d283cc0942881d4dc27d7dffdaf677c22 Mon Sep 17 00:00:00 2001 From: Christian Koop Date: Thu, 29 Sep 2022 21:52:59 +0200 Subject: [PATCH] Adds a simple http client This is intended to standardize how we do these request in the core. It doesn't do much but it will sufice for now to be used in the new localization system. --- .../com/songoda/core/http/HttpClient.java | 9 ++++ .../com/songoda/core/http/HttpResponse.java | 11 ++++ .../songoda/core/http/HttpResponseImpl.java | 54 +++++++++++++++++++ .../songoda/core/http/SimpleHttpClient.java | 21 ++++++++ .../http/UnexpectedHttpStatusException.java | 15 ++++++ .../com/songoda/core/http/MockHttpClient.java | 22 ++++++++ .../songoda/core/http/MockHttpResponse.java | 25 +++++++++ 7 files changed, 157 insertions(+) create mode 100644 Core/src/main/java/com/songoda/core/http/HttpClient.java create mode 100644 Core/src/main/java/com/songoda/core/http/HttpResponse.java create mode 100644 Core/src/main/java/com/songoda/core/http/HttpResponseImpl.java create mode 100644 Core/src/main/java/com/songoda/core/http/SimpleHttpClient.java create mode 100644 Core/src/main/java/com/songoda/core/http/UnexpectedHttpStatusException.java create mode 100644 Core/src/test/java/com/songoda/core/http/MockHttpClient.java create mode 100644 Core/src/test/java/com/songoda/core/http/MockHttpResponse.java diff --git a/Core/src/main/java/com/songoda/core/http/HttpClient.java b/Core/src/main/java/com/songoda/core/http/HttpClient.java new file mode 100644 index 00000000..95037834 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/http/HttpClient.java @@ -0,0 +1,9 @@ +package com.songoda.core.http; + +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; + +public interface HttpClient { + @NotNull HttpResponse get(String url) throws IOException; +} diff --git a/Core/src/main/java/com/songoda/core/http/HttpResponse.java b/Core/src/main/java/com/songoda/core/http/HttpResponse.java new file mode 100644 index 00000000..a5b519bb --- /dev/null +++ b/Core/src/main/java/com/songoda/core/http/HttpResponse.java @@ -0,0 +1,11 @@ +package com.songoda.core.http; + +import java.io.IOException; + +public interface HttpResponse { + int getResponseCode() throws IOException; + + byte[] getBody() throws IOException; + + String getBodyAsString() throws IOException; +} diff --git a/Core/src/main/java/com/songoda/core/http/HttpResponseImpl.java b/Core/src/main/java/com/songoda/core/http/HttpResponseImpl.java new file mode 100644 index 00000000..f713b98d --- /dev/null +++ b/Core/src/main/java/com/songoda/core/http/HttpResponseImpl.java @@ -0,0 +1,54 @@ +package com.songoda.core.http; + +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.nio.charset.StandardCharsets; + +public class HttpResponseImpl implements HttpResponse, AutoCloseable { + protected final HttpURLConnection connection; + + protected byte[] body; + + HttpResponseImpl(HttpURLConnection connection) throws IOException { + this.connection = connection; + + this.connection.connect(); + } + + public int getResponseCode() throws IOException { + int statusCode = this.connection.getResponseCode(); + + if (statusCode == -1) { + throw new IOException("HTTP Status Code is -1"); + } + + return statusCode; + } + + public byte[] getBody() throws IOException { + if (this.body == null) { + try (InputStream in = this.connection.getInputStream(); + InputStream err = this.connection.getErrorStream()) { + if (err != null) { + this.body = IOUtils.toByteArray(err); + } else { + this.body = IOUtils.toByteArray(in); + } + } + } + + return this.body; + } + + public String getBodyAsString() throws IOException { + return new String(getBody(), StandardCharsets.UTF_8); + } + + @Override + public void close() throws Exception { + this.connection.disconnect(); + } +} diff --git a/Core/src/main/java/com/songoda/core/http/SimpleHttpClient.java b/Core/src/main/java/com/songoda/core/http/SimpleHttpClient.java new file mode 100644 index 00000000..3ce9e606 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/http/SimpleHttpClient.java @@ -0,0 +1,21 @@ +package com.songoda.core.http; + +import com.songoda.core.SongodaCore; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +public class SimpleHttpClient implements HttpClient { + public @NotNull HttpResponse get(String url) throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setInstanceFollowRedirects(true); + connection.setConnectTimeout(5000); + connection.setReadTimeout(5000); + + connection.setRequestProperty("User-Agent", "SongodaCore/" + SongodaCore.getVersion() + " (+https://github.com/songoda/SongodaCore)"); + + return new HttpResponseImpl(connection); + } +} diff --git a/Core/src/main/java/com/songoda/core/http/UnexpectedHttpStatusException.java b/Core/src/main/java/com/songoda/core/http/UnexpectedHttpStatusException.java new file mode 100644 index 00000000..3229448c --- /dev/null +++ b/Core/src/main/java/com/songoda/core/http/UnexpectedHttpStatusException.java @@ -0,0 +1,15 @@ +package com.songoda.core.http; + +import java.io.IOException; + +public class UnexpectedHttpStatusException extends IOException { + public final int responseCode; + public final String url; + + public UnexpectedHttpStatusException(int responseCode, String url) { + super("Got HTTP Status Code " + responseCode + ": " + url); + + this.responseCode = responseCode; + this.url = url; + } +} diff --git a/Core/src/test/java/com/songoda/core/http/MockHttpClient.java b/Core/src/test/java/com/songoda/core/http/MockHttpClient.java new file mode 100644 index 00000000..ed329953 --- /dev/null +++ b/Core/src/test/java/com/songoda/core/http/MockHttpClient.java @@ -0,0 +1,22 @@ +package com.songoda.core.http; + +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedList; +import java.util.List; + +public class MockHttpClient implements HttpClient { + public HttpResponse returnValue; + public List callsOnGet = new LinkedList<>(); + + public MockHttpClient(HttpResponse returnValue) { + this.returnValue = returnValue; + } + + @Override + public @NotNull HttpResponse get(String url) { + this.callsOnGet.add(url); + + return this.returnValue; + } +} diff --git a/Core/src/test/java/com/songoda/core/http/MockHttpResponse.java b/Core/src/test/java/com/songoda/core/http/MockHttpResponse.java new file mode 100644 index 00000000..3a9a48cf --- /dev/null +++ b/Core/src/test/java/com/songoda/core/http/MockHttpResponse.java @@ -0,0 +1,25 @@ +package com.songoda.core.http; + +import java.nio.charset.StandardCharsets; + +public class MockHttpResponse implements HttpResponse { + public int responseCode; + public byte[] body; + + public MockHttpResponse(int responseCode, byte[] body) { + this.responseCode = responseCode; + this.body = body; + } + + public int getResponseCode() { + return this.responseCode; + } + + public byte[] getBody() { + return this.body; + } + + public String getBodyAsString() { + return new String(getBody(), StandardCharsets.UTF_8); + } +}