Skip to content

Commit f9cbca2

Browse files
release: 2.17.0 (#546)
* chore(internal): refactor delegating from client to options * feat(client): allow setting additional multipart body props * feat(client): add https config options * release: 2.17.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent 71cf8ab commit f9cbca2

File tree

15 files changed

+794
-147
lines changed

15 files changed

+794
-147
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.16.0"
2+
".": "2.17.0"
33
}

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## 2.17.0 (2025-07-21)
4+
5+
Full Changelog: [v2.16.0...v2.17.0](https://github.com/openai/openai-java/compare/v2.16.0...v2.17.0)
6+
7+
### Features
8+
9+
* **client:** add https config options ([3f74519](https://github.com/openai/openai-java/commit/3f745195fa5d72ee72653adbd8087915c0db2fa5))
10+
* **client:** allow setting additional multipart body props ([220503e](https://github.com/openai/openai-java/commit/220503efc745bd1c74c02f1d4d6d3305198bf942))
11+
12+
13+
### Chores
14+
15+
* **internal:** refactor delegating from client to options ([e89596d](https://github.com/openai/openai-java/commit/e89596d624fd77fdef750fb65a9ca5c6497e76cb))
16+
317
## 2.16.0 (2025-07-17)
418

519
Full Changelog: [v2.15.0...v2.16.0](https://github.com/openai/openai-java/compare/v2.15.0...v2.16.0)

README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
<!-- x-release-please-start-version -->
44

5-
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/2.16.0)
6-
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/2.16.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/2.16.0)
5+
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/2.17.0)
6+
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/2.17.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/2.17.0)
77

88
<!-- x-release-please-end -->
99

1010
The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https://platform.openai.com/docs) from applications written in Java.
1111

1212
<!-- x-release-please-start-version -->
1313

14-
The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/2.16.0).
14+
The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/2.17.0).
1515

1616
<!-- x-release-please-end -->
1717

@@ -22,7 +22,7 @@ The REST API documentation can be found on [platform.openai.com](https://platfor
2222
### Gradle
2323

2424
```kotlin
25-
implementation("com.openai:openai-java:2.16.0")
25+
implementation("com.openai:openai-java:2.17.0")
2626
```
2727

2828
### Maven
@@ -31,7 +31,7 @@ implementation("com.openai:openai-java:2.16.0")
3131
<dependency>
3232
<groupId>com.openai</groupId>
3333
<artifactId>openai-java</artifactId>
34-
<version>2.16.0</version>
34+
<version>2.17.0</version>
3535
</dependency>
3636
```
3737

@@ -1398,6 +1398,27 @@ OpenAIClient client = OpenAIOkHttpClient.builder()
13981398
.build();
13991399
```
14001400

1401+
### HTTPS
1402+
1403+
> [!NOTE]
1404+
> Most applications should not call these methods, and instead use the system defaults. The defaults include
1405+
> special optimizations that can be lost if the implementations are modified.
1406+
1407+
To configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:
1408+
1409+
```java
1410+
import com.openai.client.OpenAIClient;
1411+
import com.openai.client.okhttp.OpenAIOkHttpClient;
1412+
1413+
OpenAIClient client = OpenAIOkHttpClient.builder()
1414+
.fromEnv()
1415+
// If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.
1416+
.sslSocketFactory(yourSSLSocketFactory)
1417+
.trustManager(yourTrustManager)
1418+
.hostnameVerifier(yourHostnameVerifier)
1419+
.build();
1420+
```
1421+
14011422
### Custom HTTP client
14021423

14031424
The SDK consists of three artifacts:

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ repositories {
88

99
allprojects {
1010
group = "com.openai"
11-
version = "2.16.0" // x-release-please-version
11+
version = "2.17.0" // x-release-please-version
1212
}
1313

1414
subprojects {

openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OkHttpClient.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import java.io.InputStream
1414
import java.net.Proxy
1515
import java.time.Duration
1616
import java.util.concurrent.CompletableFuture
17+
import javax.net.ssl.HostnameVerifier
18+
import javax.net.ssl.SSLSocketFactory
19+
import javax.net.ssl.X509TrustManager
1720
import okhttp3.Call
1821
import okhttp3.Callback
1922
import okhttp3.HttpUrl.Companion.toHttpUrl
@@ -189,13 +192,28 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC
189192

190193
private var timeout: Timeout = Timeout.default()
191194
private var proxy: Proxy? = null
195+
private var sslSocketFactory: SSLSocketFactory? = null
196+
private var trustManager: X509TrustManager? = null
197+
private var hostnameVerifier: HostnameVerifier? = null
192198

193199
fun timeout(timeout: Timeout) = apply { this.timeout = timeout }
194200

195201
fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())
196202

197203
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
198204

205+
fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
206+
this.sslSocketFactory = sslSocketFactory
207+
}
208+
209+
fun trustManager(trustManager: X509TrustManager?) = apply {
210+
this.trustManager = trustManager
211+
}
212+
213+
fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
214+
this.hostnameVerifier = hostnameVerifier
215+
}
216+
199217
fun build(): OkHttpClient =
200218
OkHttpClient(
201219
okhttp3.OkHttpClient.Builder()
@@ -204,6 +222,19 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC
204222
.writeTimeout(timeout.write())
205223
.callTimeout(timeout.request())
206224
.proxy(proxy)
225+
.apply {
226+
val sslSocketFactory = sslSocketFactory
227+
val trustManager = trustManager
228+
if (sslSocketFactory != null && trustManager != null) {
229+
sslSocketFactory(sslSocketFactory, trustManager)
230+
} else {
231+
check((sslSocketFactory != null) == (trustManager != null)) {
232+
"Both or none of `sslSocketFactory` and `trustManager` must be set, but only one was set"
233+
}
234+
}
235+
236+
hostnameVerifier?.let(::hostnameVerifier)
237+
}
207238
.build()
208239
.apply {
209240
// We usually make all our requests to the same host so it makes sense to

openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt

Lines changed: 116 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ import com.openai.core.ClientOptions
1010
import com.openai.core.Timeout
1111
import com.openai.core.http.Headers
1212
import com.openai.core.http.QueryParams
13+
import com.openai.core.jsonMapper
1314
import com.openai.credential.Credential
1415
import java.net.Proxy
1516
import java.time.Clock
1617
import java.time.Duration
1718
import java.util.Optional
1819
import java.util.concurrent.Executor
20+
import javax.net.ssl.HostnameVerifier
21+
import javax.net.ssl.SSLSocketFactory
22+
import javax.net.ssl.X509TrustManager
1923
import kotlin.jvm.optionals.getOrNull
2024

2125
class OpenAIOkHttpClient private constructor() {
@@ -32,10 +36,63 @@ class OpenAIOkHttpClient private constructor() {
3236
class Builder internal constructor() {
3337

3438
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
35-
private var timeout: Timeout = Timeout.default()
3639
private var proxy: Proxy? = null
40+
private var sslSocketFactory: SSLSocketFactory? = null
41+
private var trustManager: X509TrustManager? = null
42+
private var hostnameVerifier: HostnameVerifier? = null
3743

38-
fun baseUrl(baseUrl: String) = apply { clientOptions.baseUrl(baseUrl) }
44+
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
45+
46+
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
47+
fun proxy(proxy: Optional<Proxy>) = proxy(proxy.getOrNull())
48+
49+
/**
50+
* The socket factory used to secure HTTPS connections.
51+
*
52+
* If this is set, then [trustManager] must also be set.
53+
*
54+
* If unset, then the system default is used. Most applications should not call this method,
55+
* and instead use the system default. The default include special optimizations that can be
56+
* lost if the implementation is modified.
57+
*/
58+
fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
59+
this.sslSocketFactory = sslSocketFactory
60+
}
61+
62+
/** Alias for calling [Builder.sslSocketFactory] with `sslSocketFactory.orElse(null)`. */
63+
fun sslSocketFactory(sslSocketFactory: Optional<SSLSocketFactory>) =
64+
sslSocketFactory(sslSocketFactory.getOrNull())
65+
66+
/**
67+
* The trust manager used to secure HTTPS connections.
68+
*
69+
* If this is set, then [sslSocketFactory] must also be set.
70+
*
71+
* If unset, then the system default is used. Most applications should not call this method,
72+
* and instead use the system default. The default include special optimizations that can be
73+
* lost if the implementation is modified.
74+
*/
75+
fun trustManager(trustManager: X509TrustManager?) = apply {
76+
this.trustManager = trustManager
77+
}
78+
79+
/** Alias for calling [Builder.trustManager] with `trustManager.orElse(null)`. */
80+
fun trustManager(trustManager: Optional<X509TrustManager>) =
81+
trustManager(trustManager.getOrNull())
82+
83+
/**
84+
* The verifier used to confirm that response certificates apply to requested hostnames for
85+
* HTTPS connections.
86+
*
87+
* If unset, then a default hostname verifier is used.
88+
*/
89+
fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
90+
this.hostnameVerifier = hostnameVerifier
91+
}
92+
93+
/** Alias for calling [Builder.hostnameVerifier] with `hostnameVerifier.orElse(null)`. */
94+
fun hostnameVerifier(hostnameVerifier: Optional<HostnameVerifier>) =
95+
hostnameVerifier(hostnameVerifier.getOrNull())
3996

4097
/**
4198
* Whether to throw an exception if any of the Jackson versions detected at runtime are
@@ -56,6 +113,54 @@ class OpenAIOkHttpClient private constructor() {
56113

57114
fun clock(clock: Clock) = apply { clientOptions.clock(clock) }
58115

116+
fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) }
117+
118+
/** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
119+
fun baseUrl(baseUrl: Optional<String>) = baseUrl(baseUrl.getOrNull())
120+
121+
fun responseValidation(responseValidation: Boolean) = apply {
122+
clientOptions.responseValidation(responseValidation)
123+
}
124+
125+
fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) }
126+
127+
/**
128+
* Sets the maximum time allowed for a complete HTTP call, not including retries.
129+
*
130+
* See [Timeout.request] for more details.
131+
*
132+
* For fine-grained control, pass a [Timeout] object.
133+
*/
134+
fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) }
135+
136+
fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }
137+
138+
fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) }
139+
140+
fun credential(credential: Credential) = apply { clientOptions.credential(credential) }
141+
142+
fun azureServiceVersion(azureServiceVersion: AzureOpenAIServiceVersion) = apply {
143+
clientOptions.azureServiceVersion(azureServiceVersion)
144+
}
145+
146+
fun organization(organization: String?) = apply { clientOptions.organization(organization) }
147+
148+
/** Alias for calling [Builder.organization] with `organization.orElse(null)`. */
149+
fun organization(organization: Optional<String>) = organization(organization.getOrNull())
150+
151+
fun project(project: String?) = apply { clientOptions.project(project) }
152+
153+
/** Alias for calling [Builder.project] with `project.orElse(null)`. */
154+
fun project(project: Optional<String>) = project(project.getOrNull())
155+
156+
fun webhookSecret(webhookSecret: String?) = apply {
157+
clientOptions.webhookSecret(webhookSecret)
158+
}
159+
160+
/** Alias for calling [Builder.webhookSecret] with `webhookSecret.orElse(null)`. */
161+
fun webhookSecret(webhookSecret: Optional<String>) =
162+
webhookSecret(webhookSecret.getOrNull())
163+
59164
fun headers(headers: Headers) = apply { clientOptions.headers(headers) }
60165

61166
fun headers(headers: Map<String, Iterable<String>>) = apply {
@@ -136,54 +241,6 @@ class OpenAIOkHttpClient private constructor() {
136241
clientOptions.removeAllQueryParams(keys)
137242
}
138243

139-
fun timeout(timeout: Timeout) = apply {
140-
clientOptions.timeout(timeout)
141-
this.timeout = timeout
142-
}
143-
144-
/**
145-
* Sets the maximum time allowed for a complete HTTP call, not including retries.
146-
*
147-
* See [Timeout.request] for more details.
148-
*
149-
* For fine-grained control, pass a [Timeout] object.
150-
*/
151-
fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())
152-
153-
fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }
154-
155-
fun proxy(proxy: Proxy) = apply { this.proxy = proxy }
156-
157-
fun responseValidation(responseValidation: Boolean) = apply {
158-
clientOptions.responseValidation(responseValidation)
159-
}
160-
161-
fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) }
162-
163-
fun credential(credential: Credential) = apply { clientOptions.credential(credential) }
164-
165-
fun azureServiceVersion(azureServiceVersion: AzureOpenAIServiceVersion) = apply {
166-
clientOptions.azureServiceVersion(azureServiceVersion)
167-
}
168-
169-
fun organization(organization: String?) = apply { clientOptions.organization(organization) }
170-
171-
/** Alias for calling [Builder.organization] with `organization.orElse(null)`. */
172-
fun organization(organization: Optional<String>) = organization(organization.getOrNull())
173-
174-
fun project(project: String?) = apply { clientOptions.project(project) }
175-
176-
/** Alias for calling [Builder.project] with `project.orElse(null)`. */
177-
fun project(project: Optional<String>) = project(project.getOrNull())
178-
179-
fun webhookSecret(webhookSecret: String?) = apply {
180-
clientOptions.webhookSecret(webhookSecret)
181-
}
182-
183-
/** Alias for calling [Builder.webhookSecret] with `webhookSecret.orElse(null)`. */
184-
fun webhookSecret(webhookSecret: Optional<String>) =
185-
webhookSecret(webhookSecret.getOrNull())
186-
187244
fun fromEnv() = apply { clientOptions.fromEnv() }
188245

189246
/**
@@ -194,7 +251,15 @@ class OpenAIOkHttpClient private constructor() {
194251
fun build(): OpenAIClient =
195252
OpenAIClientImpl(
196253
clientOptions
197-
.httpClient(OkHttpClient.builder().timeout(timeout).proxy(proxy).build())
254+
.httpClient(
255+
OkHttpClient.builder()
256+
.timeout(clientOptions.timeout())
257+
.proxy(proxy)
258+
.sslSocketFactory(sslSocketFactory)
259+
.trustManager(trustManager)
260+
.hostnameVerifier(hostnameVerifier)
261+
.build()
262+
)
198263
.build()
199264
)
200265
}

0 commit comments

Comments
 (0)