Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Allow custom request timeouts to be passed to OkHttp client (#86) #134

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,20 @@ import tbdex.sdk.protocol.models.Offering
import tbdex.sdk.protocol.serialization.Json
import tbdex.sdk.protocol.serialization.Json.jsonMapper
import web5.sdk.dids.Did
import java.time.Duration

/**
* A client of the tbDEX HTTP interface for communicating with a PFI.
*
* An optional request timeout may be specified. Even if set to Duration.ZERO (default), the default OkHttp timeouts
* will be enforced: 10 seconds to connect, 10 seconds to write the request and 10 seconds to read the response.
*/
object TbdexHttpClient {
private val client = OkHttpClient()
class TbdexHttpClient(timeout: Duration) {
private val client = OkHttpClient.Builder().callTimeout(timeout).build()
private val jsonMediaType = "application/json; charset=utf-8".toMediaType()
private const val JSON_HEADER = "application/json"
private val JSON_HEADER = "application/json"

constructor() : this(Duration.ZERO)

/**
* Fetches offerings from a PFI.
Expand All @@ -36,7 +42,7 @@ object TbdexHttpClient {
* @return A list of [Offering] matching the request.
* @throws TbdexResponseException for request or response errors.
*/
fun getOfferings(pfiDid: String, filter: GetOfferingsFilter? = null): List<Offering> {
fun getOfferings(pfiDid: String, filter: GetOfferingsFilter? = null, timeout: Duration? = null): List<Offering> {
val pfiServiceEndpoint = getPfiServiceEndpoint(pfiDid)
val baseUrl = "$pfiServiceEndpoint/offerings/"

Expand All @@ -51,7 +57,12 @@ object TbdexHttpClient {
.get()
.build()

val response: Response = client.newCall(request).execute()
var c = client;
if(timeout != null) {
c = OkHttpClient().newBuilder().callTimeout(timeout).build();
}

val response: Response = c.newCall(request).execute()
when {
response.isSuccessful -> {
val responseString = response.body?.string()
Expand All @@ -73,7 +84,7 @@ object TbdexHttpClient {
* @param message The [Message] object containing the message details to be sent.
* @throws TbdexResponseException for request or response errors.
*/
fun sendMessage(message: Message) {
fun sendMessage(message: Message, timeout: Duration? = null) {
Validator.validateMessage(message)
message.verify()

Expand All @@ -94,7 +105,12 @@ object TbdexHttpClient {

println("attempting to send message to: ${request.url}")

val response: Response = client.newCall(request).execute()
var c = client;
if(timeout != null) {
c = OkHttpClient().newBuilder().callTimeout(timeout).build();
}

val response: Response = c.newCall(request).execute()
if (!response.isSuccessful) {
throw buildResponseException(response)
}
Expand All @@ -109,7 +125,7 @@ object TbdexHttpClient {
* @return An [Exchange] containing the requested exchange.
* @throws TbdexResponseException for request or response errors.
*/
fun getExchange(pfiDid: String, requesterDid: Did, exchangeId: String): Exchange {
fun getExchange(pfiDid: String, requesterDid: Did, exchangeId: String, timeout: Duration? = null): Exchange {
val pfiServiceEndpoint = getPfiServiceEndpoint(pfiDid)
val baseUrl = "$pfiServiceEndpoint/exchanges/$exchangeId"
val requestToken = generateRequestToken(requesterDid)
Expand All @@ -121,7 +137,12 @@ object TbdexHttpClient {
.get()
.build()

val response: Response = client.newCall(request).execute()
var c = client;
if(timeout != null) {
c = OkHttpClient().newBuilder().callTimeout(timeout).build();
}

val response: Response = c.newCall(request).execute()
println("attempting to get exchange: ${request.url}")

when {
Expand All @@ -147,7 +168,8 @@ object TbdexHttpClient {
* @return A list of matching [Exchange].
* @throws TbdexResponseException for request or response errors.
*/
fun getExchanges(pfiDid: String, requesterDid: Did, filter: GetExchangesFilter? = null): List<Exchange> {
fun getExchanges(pfiDid: String, requesterDid: Did, filter: GetExchangesFilter? = null,
timeout: Duration? = null): List<Exchange> {
val pfiServiceEndpoint = getPfiServiceEndpoint(pfiDid)
val baseUrl = "$pfiServiceEndpoint/exchanges/"
val requestToken = generateRequestToken(requesterDid)
Expand All @@ -165,7 +187,12 @@ object TbdexHttpClient {

println("attempting to get exchanges: ${request.url}")

val response: Response = client.newCall(request).execute()
var c = client;
if(timeout != null) {
c = OkHttpClient().newBuilder().callTimeout(timeout).build();
}

val response: Response = c.newCall(request).execute()
when {
response.isSuccessful -> {
val jsonNode = jsonMapper.readTree(response.body?.string())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class E2ETest {
@Test
@Disabled("Must be run alongside tbdex-mock-pfi. See README for details")
fun `tests e2e flow`() {
val client = TbdexHttpClient
val client = TbdexHttpClient()

val keyManager = InMemoryKeyManager()
val pfiDid = DidDht.create(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class TbdexHttpClientTest {
val mockResponseString = Json.jsonMapper.writeValueAsString(mapOf("data" to mockOfferings))
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_OK))

val response = TbdexHttpClient.getOfferings(pfiDid.uri, null)
val response = TbdexHttpClient().getOfferings(pfiDid.uri, null)

assertEquals(1, response.size)
}
Expand All @@ -80,7 +80,7 @@ class TbdexHttpClientTest {
val mockResponseString = Json.jsonMapper.writeValueAsString(errorDetails)
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST))

assertThrows<TbdexResponseException> { TbdexHttpClient.getOfferings(pfiDid.uri, null) }
assertThrows<TbdexResponseException> { TbdexHttpClient().getOfferings(pfiDid.uri, null) }
}

@Test
Expand All @@ -89,7 +89,7 @@ class TbdexHttpClientTest {
server.enqueue(MockResponse().setResponseCode(HttpURLConnection.HTTP_ACCEPTED))

val rfq = TestData.getRfq(pfiDid.uri, TypeId.generate("offering"))
assertDoesNotThrow { TbdexHttpClient.sendMessage(rfq) }
assertDoesNotThrow { TbdexHttpClient().sendMessage(rfq) }
}

@Test
Expand All @@ -112,7 +112,7 @@ class TbdexHttpClientTest {
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST))

val rfq = TestData.getRfq(pfiDid.uri, TypeId.generate("offering"))
val exception = assertThrows<TbdexResponseException> { TbdexHttpClient.sendMessage(rfq) }
val exception = assertThrows<TbdexResponseException> { TbdexHttpClient().sendMessage(rfq) }
assertEquals(1, exception.errors?.size)
assertEquals("400", exception.errors?.get(0)?.status)
}
Expand All @@ -124,7 +124,7 @@ class TbdexHttpClientTest {
val mockResponseString = Json.jsonMapper.writeValueAsString(mapOf("data" to exchange))
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_OK))

val response = TbdexHttpClient.getExchange(pfiDid.uri, alice, "exchange_1234")
val response = TbdexHttpClient().getExchange(pfiDid.uri, alice, "exchange_1234")

assertEquals(offeringId, (response[0] as Rfq).data.offeringId)
}
Expand All @@ -149,7 +149,7 @@ class TbdexHttpClientTest {
val mockResponseString = Json.jsonMapper.writeValueAsString(errorDetails)
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST))

assertThrows<TbdexResponseException> { TbdexHttpClient.getExchange(pfiDid.uri, alice, "exchange_1234") }
assertThrows<TbdexResponseException> { TbdexHttpClient().getExchange(pfiDid.uri, alice, "exchange_1234") }
}

@Test
Expand All @@ -159,7 +159,7 @@ class TbdexHttpClientTest {
val mockResponseString = Json.jsonMapper.writeValueAsString(mapOf("data" to exchanges))
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_OK))

val response = TbdexHttpClient.getExchanges(pfiDid.uri, alice)
val response = TbdexHttpClient().getExchanges(pfiDid.uri, alice)

assertEquals(offeringId, (response[0][0] as Rfq).data.offeringId)
}
Expand Down Expand Up @@ -196,7 +196,7 @@ class TbdexHttpClientTest {
val mockResponseString = Json.jsonMapper.writeValueAsString(errorDetails)
server.enqueue(MockResponse().setBody(mockResponseString).setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST))

assertThrows<TbdexResponseException> { TbdexHttpClient.getExchanges(pfiDid.uri, alice) }
assertThrows<TbdexResponseException> { TbdexHttpClient().getExchanges(pfiDid.uri, alice) }
}

@AfterEach
Expand Down
Loading