Skip to content

Commit 6172f77

Browse files
feat(client): implement per-endpoint base URL support
Refactor `HttpRequest` to always take a `baseUrl`, instead of storing this in `OkHttpClient`. This allows better reuse of `OkHttpClient` when changing the `baseUrl`.
1 parent fdf951c commit 6172f77

File tree

62 files changed

+275
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+275
-44
lines changed

orb-java-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OkHttpClient.kt

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.withorb.api.client.okhttp
22

33
import com.withorb.api.core.RequestOptions
44
import com.withorb.api.core.Timeout
5-
import com.withorb.api.core.checkRequired
65
import com.withorb.api.core.http.Headers
76
import com.withorb.api.core.http.HttpClient
87
import com.withorb.api.core.http.HttpMethod
@@ -17,7 +16,6 @@ import java.time.Duration
1716
import java.util.concurrent.CompletableFuture
1817
import okhttp3.Call
1918
import okhttp3.Callback
20-
import okhttp3.HttpUrl
2119
import okhttp3.HttpUrl.Companion.toHttpUrl
2220
import okhttp3.MediaType
2321
import okhttp3.MediaType.Companion.toMediaType
@@ -28,8 +26,7 @@ import okhttp3.Response
2826
import okhttp3.logging.HttpLoggingInterceptor
2927
import okio.BufferedSink
3028

31-
class OkHttpClient
32-
private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val baseUrl: HttpUrl) :
29+
class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpClient) :
3330
HttpClient {
3431

3532
override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse {
@@ -140,11 +137,7 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
140137
}
141138

142139
private fun HttpRequest.toUrl(): String {
143-
url?.let {
144-
return it
145-
}
146-
147-
val builder = baseUrl.newBuilder()
140+
val builder = baseUrl.toHttpUrl().newBuilder()
148141
pathSegments.forEach(builder::addPathSegment)
149142
queryParams.keys().forEach { key ->
150143
queryParams.values(key).forEach { builder.addQueryParameter(key, it) }
@@ -194,12 +187,9 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
194187

195188
class Builder internal constructor() {
196189

197-
private var baseUrl: HttpUrl? = null
198190
private var timeout: Timeout = Timeout.default()
199191
private var proxy: Proxy? = null
200192

201-
fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl.toHttpUrl() }
202-
203193
fun timeout(timeout: Timeout) = apply { this.timeout = timeout }
204194

205195
fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())
@@ -214,8 +204,7 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
214204
.writeTimeout(timeout.write())
215205
.callTimeout(timeout.request())
216206
.proxy(proxy)
217-
.build(),
218-
checkRequired("baseUrl", baseUrl),
207+
.build()
219208
)
220209
}
221210
}

orb-java-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClient.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,7 @@ class OrbOkHttpClient private constructor() {
176176
fun build(): OrbClient =
177177
OrbClientImpl(
178178
clientOptions
179-
.httpClient(
180-
OkHttpClient.builder()
181-
.baseUrl(clientOptions.baseUrl())
182-
.timeout(timeout)
183-
.proxy(proxy)
184-
.build()
185-
)
179+
.httpClient(OkHttpClient.builder().timeout(timeout).proxy(proxy).build())
186180
.build()
187181
)
188182
}

orb-java-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClientAsync.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,7 @@ class OrbOkHttpClientAsync private constructor() {
176176
fun build(): OrbClientAsync =
177177
OrbClientAsyncImpl(
178178
clientOptions
179-
.httpClient(
180-
OkHttpClient.builder()
181-
.baseUrl(clientOptions.baseUrl())
182-
.timeout(timeout)
183-
.proxy(proxy)
184-
.build()
185-
)
179+
.httpClient(OkHttpClient.builder().timeout(timeout).proxy(proxy).build())
186180
.build()
187181
)
188182
}

orb-java-core/src/main/kotlin/com/withorb/api/core/ClientOptions.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private constructor(
2424
@get:JvmName("jsonMapper") val jsonMapper: JsonMapper,
2525
@get:JvmName("streamHandlerExecutor") val streamHandlerExecutor: Executor,
2626
@get:JvmName("clock") val clock: Clock,
27-
@get:JvmName("baseUrl") val baseUrl: String,
27+
private val baseUrl: String?,
2828
@get:JvmName("headers") val headers: Headers,
2929
@get:JvmName("queryParams") val queryParams: QueryParams,
3030
@get:JvmName("responseValidation") val responseValidation: Boolean,
@@ -40,6 +40,8 @@ private constructor(
4040
}
4141
}
4242

43+
fun baseUrl(): String = baseUrl ?: PRODUCTION_URL
44+
4345
fun webhookSecret(): Optional<String> = Optional.ofNullable(webhookSecret)
4446

4547
fun toBuilder() = Builder().from(this)
@@ -70,7 +72,7 @@ private constructor(
7072
private var jsonMapper: JsonMapper = jsonMapper()
7173
private var streamHandlerExecutor: Executor? = null
7274
private var clock: Clock = Clock.systemUTC()
73-
private var baseUrl: String = PRODUCTION_URL
75+
private var baseUrl: String? = null
7476
private var headers: Headers.Builder = Headers.builder()
7577
private var queryParams: QueryParams.Builder = QueryParams.builder()
7678
private var responseValidation: Boolean = false
@@ -110,7 +112,10 @@ private constructor(
110112

111113
fun clock(clock: Clock) = apply { this.clock = clock }
112114

113-
fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl }
115+
fun baseUrl(baseUrl: String?) = apply { this.baseUrl = baseUrl }
116+
117+
/** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
118+
fun baseUrl(baseUrl: Optional<String>) = baseUrl(baseUrl.getOrNull())
114119

115120
fun responseValidation(responseValidation: Boolean) = apply {
116121
this.responseValidation = responseValidation
@@ -208,8 +213,6 @@ private constructor(
208213

209214
fun removeAllQueryParams(keys: Set<String>) = apply { queryParams.removeAll(keys) }
210215

211-
fun baseUrl(): String = baseUrl
212-
213216
fun fromEnv() = apply {
214217
System.getenv("ORB_BASE_URL")?.let { baseUrl(it) }
215218
System.getenv("ORB_API_KEY")?.let { apiKey(it) }

orb-java-core/src/main/kotlin/com/withorb/api/core/http/HttpRequest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.withorb.api.core.toImmutable
66
class HttpRequest
77
private constructor(
88
@get:JvmName("method") val method: HttpMethod,
9-
@get:JvmName("url") val url: String?,
9+
@get:JvmName("baseUrl") val baseUrl: String,
1010
@get:JvmName("pathSegments") val pathSegments: List<String>,
1111
@get:JvmName("headers") val headers: Headers,
1212
@get:JvmName("queryParams") val queryParams: QueryParams,
@@ -16,7 +16,7 @@ private constructor(
1616
fun toBuilder(): Builder = Builder().from(this)
1717

1818
override fun toString(): String =
19-
"HttpRequest{method=$method, url=$url, pathSegments=$pathSegments, headers=$headers, queryParams=$queryParams, body=$body}"
19+
"HttpRequest{method=$method, baseUrl=$baseUrl, pathSegments=$pathSegments, headers=$headers, queryParams=$queryParams, body=$body}"
2020

2121
companion object {
2222
@JvmStatic fun builder() = Builder()
@@ -25,7 +25,7 @@ private constructor(
2525
class Builder internal constructor() {
2626

2727
private var method: HttpMethod? = null
28-
private var url: String? = null
28+
private var baseUrl: String? = null
2929
private var pathSegments: MutableList<String> = mutableListOf()
3030
private var headers: Headers.Builder = Headers.builder()
3131
private var queryParams: QueryParams.Builder = QueryParams.builder()
@@ -34,7 +34,7 @@ private constructor(
3434
@JvmSynthetic
3535
internal fun from(request: HttpRequest) = apply {
3636
method = request.method
37-
url = request.url
37+
baseUrl = request.baseUrl
3838
pathSegments = request.pathSegments.toMutableList()
3939
headers = request.headers.toBuilder()
4040
queryParams = request.queryParams.toBuilder()
@@ -43,7 +43,7 @@ private constructor(
4343

4444
fun method(method: HttpMethod) = apply { this.method = method }
4545

46-
fun url(url: String) = apply { this.url = url }
46+
fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl }
4747

4848
fun addPathSegment(pathSegment: String) = apply { pathSegments.add(pathSegment) }
4949

@@ -136,7 +136,7 @@ private constructor(
136136
fun build(): HttpRequest =
137137
HttpRequest(
138138
checkRequired("method", method),
139-
url,
139+
checkRequired("baseUrl", baseUrl),
140140
pathSegments.toImmutable(),
141141
headers.build(),
142142
queryParams.build(),

orb-java-core/src/main/kotlin/com/withorb/api/services/async/AlertServiceAsyncImpl.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
113113
val request =
114114
HttpRequest.builder()
115115
.method(HttpMethod.GET)
116+
.baseUrl(clientOptions.baseUrl())
116117
.addPathSegments("alerts", params._pathParam(0))
117118
.build()
118119
.prepareAsync(clientOptions, params)
@@ -145,6 +146,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
145146
val request =
146147
HttpRequest.builder()
147148
.method(HttpMethod.PUT)
149+
.baseUrl(clientOptions.baseUrl())
148150
.addPathSegments("alerts", params._pathParam(0))
149151
.body(json(clientOptions.jsonMapper, params._body()))
150152
.build()
@@ -176,6 +178,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
176178
val request =
177179
HttpRequest.builder()
178180
.method(HttpMethod.GET)
181+
.baseUrl(clientOptions.baseUrl())
179182
.addPathSegments("alerts")
180183
.build()
181184
.prepareAsync(clientOptions, params)
@@ -216,6 +219,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
216219
val request =
217220
HttpRequest.builder()
218221
.method(HttpMethod.POST)
222+
.baseUrl(clientOptions.baseUrl())
219223
.addPathSegments("alerts", "customer_id", params._pathParam(0))
220224
.body(json(clientOptions.jsonMapper, params._body()))
221225
.build()
@@ -249,6 +253,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
249253
val request =
250254
HttpRequest.builder()
251255
.method(HttpMethod.POST)
256+
.baseUrl(clientOptions.baseUrl())
252257
.addPathSegments("alerts", "external_customer_id", params._pathParam(0))
253258
.body(json(clientOptions.jsonMapper, params._body()))
254259
.build()
@@ -282,6 +287,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
282287
val request =
283288
HttpRequest.builder()
284289
.method(HttpMethod.POST)
290+
.baseUrl(clientOptions.baseUrl())
285291
.addPathSegments("alerts", "subscription_id", params._pathParam(0))
286292
.body(json(clientOptions.jsonMapper, params._body()))
287293
.build()
@@ -315,6 +321,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
315321
val request =
316322
HttpRequest.builder()
317323
.method(HttpMethod.POST)
324+
.baseUrl(clientOptions.baseUrl())
318325
.addPathSegments("alerts", params._pathParam(0), "disable")
319326
.apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } }
320327
.build()
@@ -348,6 +355,7 @@ class AlertServiceAsyncImpl internal constructor(private val clientOptions: Clie
348355
val request =
349356
HttpRequest.builder()
350357
.method(HttpMethod.POST)
358+
.baseUrl(clientOptions.baseUrl())
351359
.addPathSegments("alerts", params._pathParam(0), "enable")
352360
.apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } }
353361
.build()

orb-java-core/src/main/kotlin/com/withorb/api/services/async/BetaServiceAsyncImpl.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class BetaServiceAsyncImpl internal constructor(private val clientOptions: Clien
8686
val request =
8787
HttpRequest.builder()
8888
.method(HttpMethod.POST)
89+
.baseUrl(clientOptions.baseUrl())
8990
.addPathSegments("plans", params._pathParam(0), "versions")
9091
.body(json(clientOptions.jsonMapper, params._body()))
9192
.build()
@@ -119,6 +120,7 @@ class BetaServiceAsyncImpl internal constructor(private val clientOptions: Clien
119120
val request =
120121
HttpRequest.builder()
121122
.method(HttpMethod.GET)
123+
.baseUrl(clientOptions.baseUrl())
122124
.addPathSegments(
123125
"plans",
124126
params._pathParam(0),
@@ -156,6 +158,7 @@ class BetaServiceAsyncImpl internal constructor(private val clientOptions: Clien
156158
val request =
157159
HttpRequest.builder()
158160
.method(HttpMethod.POST)
161+
.baseUrl(clientOptions.baseUrl())
159162
.addPathSegments("plans", params._pathParam(0), "set_default_version")
160163
.body(json(clientOptions.jsonMapper, params._body()))
161164
.build()

orb-java-core/src/main/kotlin/com/withorb/api/services/async/CouponServiceAsyncImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class CouponServiceAsyncImpl internal constructor(private val clientOptions: Cli
9292
val request =
9393
HttpRequest.builder()
9494
.method(HttpMethod.POST)
95+
.baseUrl(clientOptions.baseUrl())
9596
.addPathSegments("coupons")
9697
.body(json(clientOptions.jsonMapper, params._body()))
9798
.build()
@@ -123,6 +124,7 @@ class CouponServiceAsyncImpl internal constructor(private val clientOptions: Cli
123124
val request =
124125
HttpRequest.builder()
125126
.method(HttpMethod.GET)
127+
.baseUrl(clientOptions.baseUrl())
126128
.addPathSegments("coupons")
127129
.build()
128130
.prepareAsync(clientOptions, params)
@@ -163,6 +165,7 @@ class CouponServiceAsyncImpl internal constructor(private val clientOptions: Cli
163165
val request =
164166
HttpRequest.builder()
165167
.method(HttpMethod.POST)
168+
.baseUrl(clientOptions.baseUrl())
166169
.addPathSegments("coupons", params._pathParam(0), "archive")
167170
.apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } }
168171
.build()
@@ -196,6 +199,7 @@ class CouponServiceAsyncImpl internal constructor(private val clientOptions: Cli
196199
val request =
197200
HttpRequest.builder()
198201
.method(HttpMethod.GET)
202+
.baseUrl(clientOptions.baseUrl())
199203
.addPathSegments("coupons", params._pathParam(0))
200204
.build()
201205
.prepareAsync(clientOptions, params)

orb-java-core/src/main/kotlin/com/withorb/api/services/async/CreditNoteServiceAsyncImpl.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class CreditNoteServiceAsyncImpl internal constructor(private val clientOptions:
7070
val request =
7171
HttpRequest.builder()
7272
.method(HttpMethod.POST)
73+
.baseUrl(clientOptions.baseUrl())
7374
.addPathSegments("credit_notes")
7475
.body(json(clientOptions.jsonMapper, params._body()))
7576
.build()
@@ -101,6 +102,7 @@ class CreditNoteServiceAsyncImpl internal constructor(private val clientOptions:
101102
val request =
102103
HttpRequest.builder()
103104
.method(HttpMethod.GET)
105+
.baseUrl(clientOptions.baseUrl())
104106
.addPathSegments("credit_notes")
105107
.build()
106108
.prepareAsync(clientOptions, params)
@@ -141,6 +143,7 @@ class CreditNoteServiceAsyncImpl internal constructor(private val clientOptions:
141143
val request =
142144
HttpRequest.builder()
143145
.method(HttpMethod.GET)
146+
.baseUrl(clientOptions.baseUrl())
144147
.addPathSegments("credit_notes", params._pathParam(0))
145148
.build()
146149
.prepareAsync(clientOptions, params)

0 commit comments

Comments
 (0)