HttpUtils methods now throw an IOException when a request isn't successful, rather than returning a Boolean. This has been the cause of previous bugs as people forget to check for the false case.

This commit is contained in:
Shams Asari 2017-11-30 17:39:51 +00:00
parent ae3a3444f2
commit 4374c32a75
6 changed files with 23 additions and 37 deletions

View File

@ -2,7 +2,6 @@ package net.corda.bank.api
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClient
import net.corda.core.contracts.Amount
import net.corda.core.messaging.startFlow import net.corda.core.messaging.startFlow
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
@ -10,7 +9,6 @@ import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.finance.flows.CashIssueAndPaymentFlow import net.corda.finance.flows.CashIssueAndPaymentFlow
import net.corda.testing.http.HttpApi import net.corda.testing.http.HttpApi
import java.util.*
/** /**
* Interface for communicating with Bank of Corda node * Interface for communicating with Bank of Corda node

View File

@ -110,7 +110,7 @@ class IRSDemoTest {
private fun runDateChange(nodeApi: HttpApi) { private fun runDateChange(nodeApi: HttpApi) {
log.info("Running date change against ${nodeApi.root}") log.info("Running date change against ${nodeApi.root}")
assertThat(nodeApi.putJson("demodate", "\"$futureDate\"")).isTrue() nodeApi.putJson("demodate", "\"$futureDate\"")
} }
private fun runTrade(nodeApi: HttpApi, oracle: Party) { private fun runTrade(nodeApi: HttpApi, oracle: Party) {
@ -123,7 +123,7 @@ class IRSDemoTest {
private fun runUploadRates(nodeApi: HttpApi) { private fun runUploadRates(nodeApi: HttpApi) {
log.info("Running upload rates against ${nodeApi.root}") log.info("Running upload rates against ${nodeApi.root}")
val fileContents = loadResourceFile("net/corda/irs/simulation/example.rates.txt") val fileContents = loadResourceFile("net/corda/irs/simulation/example.rates.txt")
assertThat(nodeApi.postPlain("fixes", fileContents)).isTrue() nodeApi.postPlain("fixes", fileContents)
} }
private fun loadResourceFile(filename: String): String { private fun loadResourceFile(filename: String): String {

View File

@ -8,7 +8,7 @@ import org.apache.commons.io.IOUtils
/** /**
* Interface for communicating with nodes running the IRS demo. * Interface for communicating with nodes running the IRS demo.
*/ */
class IRSDemoClientApi(private val hostAndPort: NetworkHostAndPort) { class IRSDemoClientApi(hostAndPort: NetworkHostAndPort) {
private val api = HttpApi.fromHostAndPort(hostAndPort, apiRoot) private val api = HttpApi.fromHostAndPort(hostAndPort, apiRoot)
fun runTrade(tradeId: String, oracleName: CordaX500Name) { fun runTrade(tradeId: String, oracleName: CordaX500Name) {
@ -17,14 +17,14 @@ class IRSDemoClientApi(private val hostAndPort: NetworkHostAndPort) {
api.postJson("deals", tradeFile) api.postJson("deals", tradeFile)
} }
fun runDateChange(newDate: String): Boolean { fun runDateChange(newDate: String) {
return api.putJson("demodate", "\"$newDate\"") api.putJson("demodate", "\"$newDate\"")
} }
// TODO: Add uploading of files to the HTTP API // TODO: Add uploading of files to the HTTP API
fun runUploadRates() { fun runUploadRates() {
val fileContents = IOUtils.toString(Thread.currentThread().contextClassLoader.getResourceAsStream("net/corda/irs/simulation/example.rates.txt"), Charsets.UTF_8.name()) val fileContents = IOUtils.toString(Thread.currentThread().contextClassLoader.getResourceAsStream("net/corda/irs/simulation/example.rates.txt"), Charsets.UTF_8.name())
check(api.postPlain("fixes", fileContents)) api.postPlain("fixes", fileContents)
println("Rates successfully uploaded!") println("Rates successfully uploaded!")
} }

View File

@ -38,7 +38,7 @@ class SimmValuationTest {
val nodeBParty = getPartyWithName(nodeAApi, nodeBLegalName) val nodeBParty = getPartyWithName(nodeAApi, nodeBLegalName)
val nodeAParty = getPartyWithName(nodeBApi, nodeALegalName) val nodeAParty = getPartyWithName(nodeBApi, nodeALegalName)
assertThat(createTradeBetween(nodeAApi, nodeBParty, testTradeId)).isTrue() createTradeBetween(nodeAApi, nodeBParty, testTradeId)
assertTradeExists(nodeBApi, nodeAParty, testTradeId) assertTradeExists(nodeBApi, nodeAParty, testTradeId)
assertTradeExists(nodeAApi, nodeBParty, testTradeId) assertTradeExists(nodeAApi, nodeBParty, testTradeId)
runValuationsBetween(nodeAApi, nodeBParty) runValuationsBetween(nodeAApi, nodeBParty)
@ -55,10 +55,10 @@ class SimmValuationTest {
return partyApi.getJson("whoami") return partyApi.getJson("whoami")
} }
private fun createTradeBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String): Boolean { private fun createTradeBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String) {
val trade = SwapDataModel(tradeId, "desc", valuationDate, "EUR_FIXED_1Y_EURIBOR_3M", val trade = SwapDataModel(tradeId, "desc", valuationDate, "EUR_FIXED_1Y_EURIBOR_3M",
valuationDate, LocalDate.parse("2020-01-02"), BuySell.BUY, BigDecimal.valueOf(1000), BigDecimal.valueOf(0.1)) valuationDate, LocalDate.parse("2020-01-02"), BuySell.BUY, BigDecimal.valueOf(1000), BigDecimal.valueOf(0.1))
return partyApi.putJson("${counterparty.id}/trades", trade) partyApi.putJson("${counterparty.id}/trades", trade)
} }
private fun assertTradeExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String) { private fun assertTradeExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String) {

View File

@ -1,6 +1,7 @@
package net.corda.testing.http package net.corda.testing.http
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import net.corda.client.jackson.JacksonSupport
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import java.net.URL import java.net.URL
@ -29,16 +30,17 @@ class HttpApi(val root: URL, val mapper: ObjectMapper = defaultMapper) {
/** /**
* Send a GET request to the path on the API specified. * Send a GET request to the path on the API specified.
*/ */
inline fun <reified T : Any> getJson(path: String, params: Map<String, String> = mapOf()) = HttpUtils.getJson<T>(URL(root, path), params, mapper) inline fun <reified T : Any> getJson(path: String, params: Map<String, String> = mapOf()): T {
return HttpUtils.getJson(URL(root, path), params, mapper)
}
private fun toJson(any: Any) = any as? String ?: HttpUtils.defaultMapper.writeValueAsString(any) private fun toJson(any: Any) = any as? String ?: HttpUtils.defaultMapper.writeValueAsString(any)
companion object { companion object {
fun fromHostAndPort(hostAndPort: NetworkHostAndPort, base: String, protocol: String = "http", mapper: ObjectMapper = defaultMapper): HttpApi fun fromHostAndPort(hostAndPort: NetworkHostAndPort, base: String, protocol: String = "http", mapper: ObjectMapper = defaultMapper): HttpApi {
= HttpApi(URL("$protocol://$hostAndPort/$base/"), mapper) return HttpApi(URL("$protocol://$hostAndPort/$base/"), mapper)
private val defaultMapper: ObjectMapper by lazy {
net.corda.client.jackson.JacksonSupport.createNonRpcMapper()
} }
private val defaultMapper: ObjectMapper by lazy { JacksonSupport.createNonRpcMapper() }
} }
} }

View File

@ -5,7 +5,6 @@ import okhttp3.MediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import org.slf4j.LoggerFactory
import java.io.IOException import java.io.IOException
import java.net.URL import java.net.URL
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -14,8 +13,6 @@ import java.util.concurrent.TimeUnit
* A small set of utilities for making HttpCalls, aimed at demos and tests. * A small set of utilities for making HttpCalls, aimed at demos and tests.
*/ */
object HttpUtils { object HttpUtils {
private val logger = LoggerFactory.getLogger(javaClass)
private val client by lazy { private val client by lazy {
OkHttpClient.Builder() OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS) .connectTimeout(5, TimeUnit.SECONDS)
@ -26,19 +23,19 @@ object HttpUtils {
net.corda.client.jackson.JacksonSupport.createNonRpcMapper() net.corda.client.jackson.JacksonSupport.createNonRpcMapper()
} }
fun putJson(url: URL, data: String): Boolean { fun putJson(url: URL, data: String) {
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data) val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data)
return makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").put(body).build()) makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").put(body).build())
} }
fun postJson(url: URL, data: String) { fun postJson(url: URL, data: String) {
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data) val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data)
makeExceptionalRequest(Request.Builder().url(url).header("Content-Type", "application/json").post(body).build()) makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").post(body).build())
} }
fun postPlain(url: URL, data: String): Boolean { fun postPlain(url: URL, data: String) {
val body = RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), data) val body = RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), data)
return makeRequest(Request.Builder().url(url).post(body).build()) makeRequest(Request.Builder().url(url).post(body).build())
} }
inline fun <reified T : Any> getJson(url: URL, params: Map<String, String> = mapOf(), mapper: ObjectMapper = defaultMapper): T { inline fun <reified T : Any> getJson(url: URL, params: Map<String, String> = mapOf(), mapper: ObjectMapper = defaultMapper): T {
@ -47,21 +44,10 @@ object HttpUtils {
return mapper.readValue(parameterisedUrl, T::class.java) return mapper.readValue(parameterisedUrl, T::class.java)
} }
// TODO Move everything to use this instead of makeRequest private fun makeRequest(request: Request) {
private fun makeExceptionalRequest(request: Request) {
val response = client.newCall(request).execute() val response = client.newCall(request).execute()
if (!response.isSuccessful) { if (!response.isSuccessful) {
throw IOException("${request.method()} to ${request.url()} returned a ${response.code()}: ${response.body().string()}") throw IOException("${request.method()} to ${request.url()} returned a ${response.code()}: ${response.body().string()}")
} }
} }
private fun makeRequest(request: Request): Boolean {
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
logger.error("Could not fulfill HTTP request of type ${request.method()} to ${request.url()}. Status Code: ${response.code()}. Message: ${response.body().string()}")
}
return response.isSuccessful
}
} }