package network.thunder.core.communication.objects.messages.impl.blockchainlistener.bciapi;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;
/**
* This is a utility class for performing API calls using GET and POST requests. It is
* possible to override these calls by implementing HttpClientInterface. Add the new
* implementation via setCustomHttpClient(...), such that it will get used globally.
*/
public class HttpClient implements HttpClientInterface {
private static final String BASE_URL = "https://blockchain.info/";
public volatile static int TIMEOUT_MS = 10000;
private static HttpClientInterface instance;
public static HttpClientInterface getInstance () {
if (instance == null) {
instance = new HttpClient();
}
return instance;
}
public static void setCustomHttpClient (HttpClientInterface httpClient) {
instance = httpClient;
}
/**
* Perform a GET request on a Blockchain.info API resource.
*
* @param resource Resource path after https://blockchain.info/api/
* @param params Map containing request parameters
* @return String response
* @throws APIException If the server returns an error
*/
public String get (String resource, Map<String, String> params) throws APIException, IOException {
return openURL(resource, params, "GET");
}
/**
* Perform a POST request on a Blockchain.info API resource.
*
* @param resource Resource path after https://blockchain.info/api/
* @param params Map containing request parameters
* @return String response
* @throws APIException If the server returns an error
*/
public String post (String resource, Map<String, String> params) throws APIException, IOException {
return openURL(resource, params, "POST");
}
private static String openURL (String resource, Map<String, String> params, String requestMethod) throws APIException, IOException {
String encodedParams = urlEncodeParams(params);
URL url = null;
APIException apiException = null;
IOException ioException = null;
String responseStr = null;
if (requestMethod.equals("GET")) {
if(encodedParams.isEmpty()) {
url = new URL(BASE_URL + resource);
}
else {
url = new URL(BASE_URL + resource + '?' + encodedParams);
}
} else if (requestMethod.equals("POST")) {
url = new URL(BASE_URL + resource);
}
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(requestMethod);
conn.setConnectTimeout(TIMEOUT_MS);
if (requestMethod.equals("POST")) {
byte[] postBytes = encodedParams.getBytes("UTF-8");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postBytes.length));
conn.getOutputStream().write(postBytes);
conn.getOutputStream().close();
}
if (conn.getResponseCode() != 200) {
apiException = new APIException(inputStreamToString(conn.getErrorStream()));
} else {
responseStr = inputStreamToString(conn.getInputStream());
}
} catch (IOException e) {
ioException = e;
} finally {
try {
if (apiException != null) {
conn.getErrorStream().close();
}
conn.getInputStream().close();
} catch (Exception ex) {
}
if (ioException != null) {
throw ioException;
}
if (apiException != null) {
throw apiException;
}
}
return responseStr;
}
private static String urlEncodeParams (Map<String, String> params) {
String result = "";
if (params != null && params.size() > 0) {
try {
StringBuilder data = new StringBuilder();
for (Entry<String, String> kvp : params.entrySet()) {
if (data.length() > 0) {
data.append('&');
}
data.append(URLEncoder.encode(kvp.getKey(), "UTF-8"));
data.append('=');
data.append(URLEncoder.encode(kvp.getValue(), "UTF-8"));
}
result = data.toString();
} catch (UnsupportedEncodingException e) {
}
}
return result;
}
private static String inputStreamToString (InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder responseStringBuilder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
responseStringBuilder.append(line);
}
return responseStringBuilder.toString();
}
}