Merge pull request #567 from Christewart/2019-07-03-resolve-http-parse-exn-bitcoind

Attempt to resolve issue #527 where bitcoind returns html indicating …
This commit is contained in:
Torkel Rogstad 2019-07-23 00:38:28 +02:00 committed by GitHub
commit 6f42dca64b

View file

@ -19,13 +19,14 @@ import play.api.libs.json._
import scala.concurrent._
import scala.concurrent.duration.DurationInt
import scala.sys.process._
import scala.util.{Failure, Success}
import scala.util.{Failure, Success, Try}
import java.nio.file.Files
import org.bitcoins.rpc.config.BitcoindAuthCredentials.CookieBased
import org.bitcoins.rpc.config.BitcoindAuthCredentials.PasswordBased
import java.nio.file.Path
import org.bitcoins.rpc.config.BitcoindAuthCredentials
import com.fasterxml.jackson.core.JsonParseException
import org.bitcoins.rpc.BitcoindException
/**
@ -180,7 +181,8 @@ trait Client extends BitcoinSLogger {
val request = buildRequest(instance, "ping", JsArray.empty)
val responseF = sendRequest(request)
val payloadF: Future[JsValue] = responseF.flatMap(getPayload)
val payloadF: Future[JsValue] =
responseF.flatMap(getPayload(_, command = "ping", request = request))
// Ping successful if no error can be parsed from the payload
val parsedF = payloadF.map { payload =>
@ -227,12 +229,10 @@ trait Client extends BitcoinSLogger {
val request = buildRequest(instance, command, JsArray(parameters))
val responseF = sendRequest(request)
val payloadF: Future[JsValue] = responseF.flatMap(getPayload)
payloadF
.map { payload =>
{
val payloadF: Future[JsValue] =
responseF.flatMap(getPayload(_, command, request, parameters))
payloadF.map { payload =>
/**
* These lines are handy if you want to inspect what's being sent to and
* returned from bitcoind before it's parsed into a Scala type. However,
@ -247,18 +247,6 @@ trait Client extends BitcoinSLogger {
json = payload,
printError = printError,
command = command)
}
}
.recover {
// this can contain sensitive information, so only log this
// if not on mainnet
case err: JsonParseException if network != MainNet =>
logger.error(s"Error when parsing result of command: $command")
logger.error(s"Parameters: ${Json.stringify(JsArray(parameters))}")
logger.error(s"Sent HTTP request: $request")
logger.error(s"Error: $err")
throw err
}
}
@ -290,11 +278,32 @@ trait Client extends BitcoinSLogger {
Http(materializer.system).singleRequest(req)
}
protected def getPayload(response: HttpResponse): Future[JsValue] = {
/** Parses the payload of the given response into JSON.
*
* The command, parameters and request are given as debug parameters,
* and only used for printing diagnostics if things go belly-up.
*/
protected def getPayload(
response: HttpResponse,
command: String,
request: HttpRequest,
parameters: List[JsValue] = List.empty): Future[JsValue] = {
val payloadF = response.entity.dataBytes.runFold(ByteString.empty)(_ ++ _)
payloadF.map { payload =>
Json.parse(payload.decodeString(ByteString.UTF_8))
payloadF.flatMap { payload =>
Try(Json.parse(payload.decodeString(ByteString.UTF_8))) match {
case Failure(err) =>
if (network != MainNet) {
logger.error(s"Error when parsing result of command: $command")
logger.error(s"Parameters: ${Json.stringify(JsArray(parameters))}")
logger.error(s"Sent HTTP request: $request")
logger.error(s"Received HTTP response: $response")
logger.error(s"Error: $err")
}
Future.failed(err)
case Success(js) => Future.successful(js)
}
}
}