mirror of
https://github.com/corda/corda.git
synced 2025-02-01 08:48:09 +00:00
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:
parent
ae3a3444f2
commit
4374c32a75
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user