Skip to content

Commit

Permalink
feat(client): send client-side timeout headers (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-app[bot] authored and stainless-bot committed Feb 3, 2025
1 parent fdeeb1d commit b3d911a
Showing 1 changed file with 58 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,11 @@ class OkHttpClient
private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val baseUrl: HttpUrl) :
HttpClient {

private fun getClient(requestOptions: RequestOptions): okhttp3.OkHttpClient {
val clientBuilder = okHttpClient.newBuilder()

val logLevel =
when (System.getenv("ANTHROPIC_LOG")?.lowercase()) {
"info" -> HttpLoggingInterceptor.Level.BASIC
"debug" -> HttpLoggingInterceptor.Level.BODY
else -> null
}
if (logLevel != null) {
clientBuilder.addNetworkInterceptor(
HttpLoggingInterceptor().setLevel(logLevel).apply {
redactHeader("X-Api-Key")
redactHeader("Authorization")
}
)
}

val timeout = requestOptions.timeout
if (timeout != null) {
clientBuilder
.connectTimeout(timeout)
.readTimeout(timeout)
.writeTimeout(timeout)
.callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
}

return clientBuilder.build()
}

override fun execute(
request: HttpRequest,
requestOptions: RequestOptions,
): HttpResponse {
val call = getClient(requestOptions).newCall(request.toRequest())
val call = newCall(request, requestOptions)

return try {
call.execute().toResponse()
Expand All @@ -84,18 +54,18 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val

request.body?.run { future.whenComplete { _, _ -> close() } }

val call = getClient(requestOptions).newCall(request.toRequest())
call.enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
future.complete(response.toResponse())
}
newCall(request, requestOptions)
.enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
future.complete(response.toResponse())
}

override fun onFailure(call: Call, e: IOException) {
future.completeExceptionally(AnthropicIoException("Request failed", e))
override fun onFailure(call: Call, e: IOException) {
future.completeExceptionally(AnthropicIoException("Request failed", e))
}
}
}
)
)

return future
}
Expand All @@ -106,7 +76,38 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
okHttpClient.cache?.close()
}

private fun HttpRequest.toRequest(): Request {
private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call {
val clientBuilder = okHttpClient.newBuilder()

val logLevel =
when (System.getenv("ANTHROPIC_LOG")?.lowercase()) {
"info" -> HttpLoggingInterceptor.Level.BASIC
"debug" -> HttpLoggingInterceptor.Level.BODY
else -> null
}
if (logLevel != null) {
clientBuilder.addNetworkInterceptor(
HttpLoggingInterceptor().setLevel(logLevel).apply {
redactHeader("X-Api-Key")
redactHeader("Authorization")
}
)
}

val timeout = requestOptions.timeout
if (timeout != null) {
clientBuilder
.connectTimeout(timeout)
.readTimeout(timeout)
.writeTimeout(timeout)
.callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
}

val client = clientBuilder.build()
return client.newCall(request.toRequest(client))
}

private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient): Request {
var body: RequestBody? = body?.toRequestBody()
// OkHttpClient always requires a request body for PUT and POST methods.
if (body == null && (method == HttpMethod.PUT || method == HttpMethod.POST)) {
Expand All @@ -118,6 +119,21 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
headers.values(name).forEach { builder.header(name, it) }
}

if (
!headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0
) {
builder.header(
"X-Stainless-Read-Timeout",
Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString()
)
}
if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) {
builder.header(
"X-Stainless-Timeout",
Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString()
)
}

return builder.build()
}

Expand Down

0 comments on commit b3d911a

Please sign in to comment.