Nucleus
Performance & native

Native HTTP — the OS trust store, pre-wired

Preconfigure java.net.http.HttpClient, OkHttp, or Ktor with the operating system trust store through NativeTrustManager.

The native HTTP modules preconfigure a Kotlin HTTP client with the operating system trust store through NativeTrustManager. HTTPS connections to hosts whose certificates come from corporate roots, MDM profiles, or SSL-inspection proxies then succeed without extra trust configuration. Nucleus ships three adapters, one each for java.net.http.HttpClient, OkHttp, and Ktor.

Add the dependency

Choose the adapter that matches your HTTP client:

ModuleArtifactClient
native-httpdev.nucleusframework:nucleus.native-httpjava.net.http.HttpClient (JDK 11+)
native-http-okhttpdev.nucleusframework:nucleus.native-http-okhttpOkHttp 4
native-http-ktordev.nucleusframework:nucleus.native-http-ktorKtor client (engine-agnostic)

Each module declares native-ssl as an api dependency, so it is pulled in transitively. You do not add native-ssl yourself.

Use the JDK HttpClient

Add native-http:

build.gradle.kts
dependencies {
    implementation("dev.nucleusframework:nucleus.native-http:2.0.7")
}

NativeHttpClient.create() returns a java.net.http.HttpClient that trusts the OS store and follows redirects. To apply native trust to your own builder, use the withNativeSsl() extension:

import dev.nucleusframework.nativehttp.NativeHttpClient
import dev.nucleusframework.nativehttp.NativeHttpClient.withNativeSsl
import java.net.http.HttpClient
import java.time.Duration

// Ready-to-use client — follows redirects
val client = NativeHttpClient.create()

// Or compose native trust into an existing builder
val custom = HttpClient.newBuilder()
    .withNativeSsl()
    .connectTimeout(Duration.ofSeconds(30))
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build()

withNativeSsl() is a member extension on NativeHttpClient. It sets the SSL context to NativeTrustManager.sslContext and disables client-certificate requests. Import it as shown to bring it into scope.

HttpClient.Builder does not follow redirects by default. NativeHttpClient.create() sets Redirect.NORMAL for you, but when you call withNativeSsl() on your own builder, add .followRedirects(HttpClient.Redirect.NORMAL) yourself — otherwise any host that returns a 302 looks like a failure.

Use OkHttp

Add native-http-okhttp. It declares OkHttp 4 as an api dependency, so you get it transitively:

build.gradle.kts
dependencies {
    implementation("dev.nucleusframework:nucleus.native-http-okhttp:2.0.7")
}
import dev.nucleusframework.nativehttp.okhttp.NativeOkHttpClient
import dev.nucleusframework.nativehttp.okhttp.NativeOkHttpClient.withNativeSsl
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit

val client = NativeOkHttpClient.create()

// Or apply native trust to your own builder
val custom = OkHttpClient.Builder()
    .withNativeSsl()
    .callTimeout(30, TimeUnit.SECONDS)
    .build()

NativeOkHttpClient.create() calls sslSocketFactory(NativeTrustManager.sslSocketFactory, NativeTrustManager.trustManager) on the builder.

Use Ktor

Add native-http-ktor and exactly one Ktor engine. The engine artifacts are compileOnly in the module, so only the engine you declare needs to be on the runtime classpath:

build.gradle.kts
dependencies {
    implementation("dev.nucleusframework:nucleus.native-http-ktor:2.0.7")
    // Pick one engine
    implementation("io.ktor:ktor-client-cio:<ktor-version>")
    // or ktor-client-java, ktor-client-okhttp, ktor-client-apache5
}
import dev.nucleusframework.nativehttp.ktor.installNativeSsl
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO

val client = HttpClient(CIO) {
    installNativeSsl()
}

installNativeSsl() is a top-level extension on HttpClientConfig. It inspects the active engine configuration and applies the matching SSL surface:

EngineWhat it configures
CIOhttps { trustManager = NativeTrustManager.trustManager }
Javaconfig { sslContext(NativeTrustManager.sslContext) }
OkHttpconfig { sslSocketFactory(NativeTrustManager.sslSocketFactory, NativeTrustManager.trustManager) }
Apache5sslContext = NativeTrustManager.sslContext

Each branch is guarded against a missing engine class, so declaring one engine does not require the others on the classpath.

How it works

Every module is a thin adapter over native-ssl. On first use, NativeTrustManager reads the OS trust store (Keychain on macOS, Crypt32 stores on Windows, the standard PEM bundle paths on Linux) and merges those anchors with the JVM defaults. The result is a single X509TrustManager that accepts both the platform root program and any certificate your IT department or user has added. See Native SSL for the per-platform details.

The adapters do not replace your HTTP client — they replace its trust manager. Connection pooling, HTTP/2, interceptors, and timeouts remain under your control.

API reference

APIDescription
NativeHttpClient.create(): HttpClientjava.net.http.HttpClient with native trust and redirect-following
HttpClient.Builder.withNativeSsl(): HttpClient.BuilderApplies native trust to a java.net.http builder
NativeOkHttpClient.create(): OkHttpClientOkHttpClient with native trust
OkHttpClient.Builder.withNativeSsl(): OkHttpClient.BuilderApplies native trust to an OkHttp builder
HttpClientConfig<T>.installNativeSsl()Applies native trust to a Ktor client, per engine

What's next

  • Native SSL — how the OS trust store is read and merged.
  • Native access — GraalVM native-image support for the runtime.
  • Quickstart — build and run your first Nucleus app.