Skip to content

Commit

Permalink
Add data for POST calls
Browse files Browse the repository at this point in the history
  • Loading branch information
chimp1984 committed Dec 14, 2020
1 parent bb80660 commit 300671a
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import bisq.core.user.Preferences;

import bisq.network.Socks5ProxyProvider;
import bisq.network.http.HttpClientUtil;
import bisq.network.http.HttpException;

import bisq.common.app.Version;
import bisq.common.util.Utilities;
Expand Down Expand Up @@ -66,13 +66,12 @@ public static void broadcastTx(Transaction tx) {
String txIdToSend = tx.getTxId().toString();
String rawTx = Utils.HEX.encode(tx.bitcoinSerialize(true));

/* // for testing
// for testing
/*
String txIdToSend = "e8049546fed938030a5c4bd1a9c8324a030362ac9a1fc49288deefac45426939";
String rawTx = "0100000001ad2fe218e18493b28ea4726ccdda128f590b2e703169159cab132bc670000240010000006a47304402207c419da4117a0b3b99a1e6e620b532cb0d4f0ca0619450564b5d70eb51d5a983022047ecc709c393b07c7c10a0e92c5eca0516ef9b1bf439ce4b21aac5f01826eb3a01210363e1776495149c5a4e92acf453a3caa19000fc804e4ba2024b600ba25e09c943ffffffff02195cff050000000017a9147d277256fce1244b857c5d6136580e931d95c80b87119f600d000000001976a9144a0f1e2f2b0d7daeec5265f10bbbbe08ed725e8988ac00000000";
*/

List<String> txBroadcastServices = preferences.getDefaultTxBroadcastServices();

String serviceAddress = getRandomServiceAddress(txBroadcastServices);
if (serviceAddress == null) {
log.warn("We don't have a serviceAddress available. txBroadcastServices={}", txBroadcastServices);
Expand All @@ -91,15 +90,15 @@ public static void broadcastTx(Transaction tx) {
}

private static void broadcastTx(String serviceAddress, String txIdToSend, String rawTx) {
TxBroadcastHttpClient httpClient = HttpClientUtil.getConfiguredHttpClient(serviceAddress,
new TxBroadcastHttpClient(socks5ProxyProvider));
TxBroadcastHttpClient httpClient = new TxBroadcastHttpClient(socks5ProxyProvider);
httpClient.setBaseUrl(serviceAddress);
httpClient.setIgnoreSocks5Proxy(false);

String url = httpClient.getBaseUrl();
log.info("We broadcast rawTx {} to {}", rawTx, url);
ListenableFuture<String> future = executorService.submit(() -> {
Thread.currentThread().setName("TxBroadcasterToMemPoolApi @" + url);
String param = "/api/tx?" + rawTx;
return httpClient.post(param, "User-Agent", "bisq/" + Version.VERSION);
Thread.currentThread().setName("MemPoolSpaceTxBroadcaster @ " + url);
return httpClient.post(rawTx, "User-Agent", "bisq/" + Version.VERSION);
});

Futures.addCallback(future, new FutureCallback<>() {
Expand All @@ -115,8 +114,21 @@ public void onSuccess(String txId) {
}

public void onFailure(@NotNull Throwable throwable) {
log.warn("Broadcast of raw tx with txId {} to {} failed. Error={}",
txIdToSend, url, throwable.toString());
Throwable cause = throwable.getCause();
if (cause instanceof HttpException) {
int responseCode = ((HttpException) cause).getResponseCode();
String message = cause.getMessage();
if (responseCode == 400 && message.equals("sendrawtransaction RPC error: {\"code\":-27,\"message\":\"Transaction already in block chain\"}")) {
log.info("Broadcast of raw tx to {} failed as transaction {} is already confirmed",
serviceAddress, txIdToSend);
} else {
log.info("Broadcast of raw tx to {} failed for transaction {}. responseCode={}, error={}",
serviceAddress, txIdToSend, responseCode, message);
}
} else {
log.warn("Broadcast of raw tx with txId {} to {} failed. Error={}",
txIdToSend, url, throwable.toString());
}
}
}, MoreExecutors.directExecutor());
}
Expand Down
93 changes: 66 additions & 27 deletions p2p/src/main/java/bisq/network/http/HttpClientImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import bisq.common.app.Version;
import bisq.common.util.Utilities;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
Expand All @@ -30,6 +31,7 @@
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
Expand All @@ -43,10 +45,13 @@
import java.net.InetSocketAddress;
import java.net.URL;

import java.nio.charset.StandardCharsets;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import java.util.UUID;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -145,9 +150,9 @@ private String requestWithoutProxy(String baseUrl,
@Nullable String headerKey,
@Nullable String headerValue) throws IOException {
long ts = System.currentTimeMillis();
String spec = baseUrl + param;
log.info("requestWithoutProxy: URL={}, httpMethod={}", spec, httpMethod);
log.info("requestWithoutProxy: URL={}, param={}, httpMethod={}", baseUrl, param, httpMethod);
try {
String spec = httpMethod == HttpMethod.GET ? baseUrl + param : baseUrl;
URL url = new URL(spec);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(httpMethod.name());
Expand All @@ -158,11 +163,17 @@ private String requestWithoutProxy(String baseUrl,
connection.setRequestProperty(headerKey, headerValue);
}

if (httpMethod == HttpMethod.POST) {
connection.setDoOutput(true);
connection.getOutputStream().write(param.getBytes(StandardCharsets.UTF_8));
}

int responseCode = connection.getResponseCode();
if (responseCode == 200) {
String response = convertInputStreamToString(connection.getInputStream());
log.info("Response for {} took {} ms. Data size:{}, response: {}",
spec,
log.info("Response from {} with param {} took {} ms. Data size:{}, response: {}",
baseUrl,
param,
System.currentTimeMillis() - ts,
Utilities.readableFileSize(response.getBytes().length),
Utilities.toTruncatedString(response));
Expand All @@ -172,15 +183,26 @@ private String requestWithoutProxy(String baseUrl,
if (errorStream != null) {
String error = convertInputStreamToString(errorStream);
errorStream.close();
throw new HttpException(error);
log.info("Received errorMsg '{}' with responseCode {} from {}. Response took: {} ms. param: {}",
error,
responseCode,
baseUrl,
System.currentTimeMillis() - ts,
param);
throw new HttpException(error, responseCode);
} else {
throw new HttpException("Request failed: Response code " + responseCode);
log.info("Response with responseCode {} from {}. Response took: {} ms. param: {}",
responseCode,
baseUrl,
System.currentTimeMillis() - ts,
param);
throw new HttpException("Request failed", responseCode);
}
}
} catch (Throwable t) {
String message = "Error at requestWithoutProxy with URL: " + spec + ". Throwable=" + t.getMessage();
log.error(message);
throw new IOException(message);
String message = "Error at requestWithoutProxy with url " + baseUrl + " and param " + param +
". Throwable=" + t.getMessage();
throw new IOException(message, t);
} finally {
try {
if (connection != null) {
Expand All @@ -201,8 +223,7 @@ private String doRequestWithProxy(String baseUrl,
@Nullable String headerKey,
@Nullable String headerValue) throws IOException {
long ts = System.currentTimeMillis();
String uri = baseUrl + param;
log.info("requestWithoutProxy: uri={}, httpMethod={}", uri, httpMethod);
log.info("requestWithoutProxy: baseUrl={}, param={}, httpMethod={}", baseUrl, param, httpMethod);
// This code is adapted from:
// http://stackoverflow.com/a/25203021/5616248

Expand All @@ -218,7 +239,7 @@ private String doRequestWithProxy(String baseUrl,
new PoolingHttpClientConnectionManager(reg) :
new PoolingHttpClientConnectionManager(reg, new FakeDnsResolver());
try {
closeableHttpClient = HttpClients.custom().setConnectionManager(cm).build();
closeableHttpClient = checkNotNull(HttpClients.custom().setConnectionManager(cm).build());
InetSocketAddress socksAddress = new InetSocketAddress(socks5Proxy.getInetAddress(), socks5Proxy.getPort());

// remove me: Use this to test with system-wide Tor proxy, or change port for another proxy.
Expand All @@ -227,23 +248,36 @@ private String doRequestWithProxy(String baseUrl,
HttpClientContext context = HttpClientContext.create();
context.setAttribute("socks.address", socksAddress);

HttpUriRequest request = getHttpUriRequest(httpMethod, uri);
if (headerKey != null && headerValue != null)
HttpUriRequest request = getHttpUriRequest(httpMethod, baseUrl, param);
if (headerKey != null && headerValue != null) {
request.setHeader(headerKey, headerValue);
}

try (CloseableHttpResponse httpResponse = checkNotNull(closeableHttpClient).execute(request, context)) {
try (CloseableHttpResponse httpResponse = closeableHttpClient.execute(request, context)) {
String response = convertInputStreamToString(httpResponse.getEntity().getContent());
log.info("Response for {} took {} ms. Data size:{}, response: {}",
uri,
System.currentTimeMillis() - ts,
Utilities.readableFileSize(response.getBytes().length),
Utilities.toTruncatedString(response));
return response;
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode == 200) {
log.info("Response from {} took {} ms. Data size:{}, response: {}, param: {}",
baseUrl,
System.currentTimeMillis() - ts,
Utilities.readableFileSize(response.getBytes().length),
Utilities.toTruncatedString(response),
param);
return response;
} else {
log.info("Received errorMsg '{}' with statusCode {} from {}. Response took: {} ms. param: {}",
response,
statusCode,
baseUrl,
System.currentTimeMillis() - ts,
param);
throw new HttpException(response, statusCode);
}
}
} catch (Throwable t) {
String message = "Error at doRequestWithProxy with URL: " + uri + ". Throwable=" + t.getMessage();
log.error(message);
throw new IOException(message);
String message = "Error at doRequestWithProxy with url " + baseUrl + " and param " + param +
". Throwable=" + t.getMessage();
throw new IOException(message, t);
} finally {
if (closeableHttpClient != null) {
closeableHttpClient.close();
Expand All @@ -253,12 +287,17 @@ private String doRequestWithProxy(String baseUrl,
}
}

private HttpUriRequest getHttpUriRequest(HttpMethod httpMethod, String uri) {
private HttpUriRequest getHttpUriRequest(HttpMethod httpMethod, String baseUrl, String param)
throws UnsupportedEncodingException {
switch (httpMethod) {
case GET:
return new HttpGet(uri);
return new HttpGet(baseUrl + param);
case POST:
return new HttpPost(uri);
HttpPost httpPost = new HttpPost(baseUrl);
HttpEntity httpEntity = new StringEntity(param);
httpPost.setEntity(httpEntity);
return httpPost;

default:
throw new IllegalArgumentException("HttpMethod not supported: " + httpMethod);
}
Expand Down
10 changes: 10 additions & 0 deletions p2p/src/main/java/bisq/network/http/HttpException.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@

package bisq.network.http;

import lombok.Getter;

public class HttpException extends Exception {
@Getter
private int responseCode;

public HttpException(String message) {
super(message);
}

public HttpException(String message, int responseCode) {
super(message);
this.responseCode = responseCode;
}
}

0 comments on commit 300671a

Please sign in to comment.