Custom Glide okhttp client

[Problem/Question]
Our project’s domain have SSL issue, then inject SSL certificate (.crt) with OkHttp client.

Glide use to that’s OkHttp client, can’t load image(s) from Sendbird through.

Sendbird profile image, and cover image required SSL inject.

Finally I’d like change to Glide custom OkHttp clinent of chat only.

[Current impact]
// How is this currently impacting your implementation?
Can’t load image

Hi @Mixmunity

Could you please explain the issue which you faced in more detail? It would be great if you could share part of the code, screenshots, and error details if it is throwing.

Thank you for response.

val okHttpClient = OkHttpClient.Builder()
                .run {
                    addInterceptor(
                        HttpLoggingInterceptor().apply {
                            level = HttpLoggingInterceptor.Level.NONE
                        },
                    )
                    sslSocketFactory(
                        selfSigningHelper.sslContext.socketFactory,
                        selfSigningHelper.tmf.trustManagers[0] as X509TrustManager,
                    )
                }
                .build()

Glide.get(context).registry.replace(
                GlideUrl::class.java,
                InputStream::class.java,
                OkHttpUrlLoader.Factory(okHttpClient),
            )

below is Log for Glide

Failed to find GeneratedAppGlideModule. You should include an annotationProcessor compile dependency on com.github.bumptech.glide:compiler in your application and a @GlideModule annotated AppGlideModule implementation or LibraryGlideModules will be silently ignored

Load failed for [thumbnail_1682147706776] with dimensions [540x540]
                                                                                                    class com.bumptech.glide.load.engine.GlideException: Failed to load resource
                                                                                                    There was 1 root cause:
                                                                                                    javax.net.ssl.SSLHandshakeException(java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.)
                                                                                                     call GlideException#logRootCauses(String) for more detail
                                                                                                      Cause (1 of 1): class com.bumptech.glide.load.engine.GlideException: Fetching data failed, class java.io.InputStream, REMOTE
                                                                                                    There was 1 root cause:
                                                                                                    javax.net.ssl.SSLHandshakeException(java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.)
                                                                                                     call GlideException#logRootCauses(String) for more detail
                                                                                                        Cause (1 of 1): class javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Root cause (1 of 1)
                                                                                                    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
                                                                                                    	at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:363)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.convertException(ConscryptEngine.java:1134)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1089)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.-$$Nest$mprocessDataFromSocket(Unknown Source:0)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
                                                                                                    	at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
                                                                                                    	at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
                                                                                                    	at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
                                                                                                    	at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
                                                                                                    	at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
                                                                                                    	at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
                                                                                                    	at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
                                                                                                    	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
                                                                                                    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                                                                                    	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
                                                                                                    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                                                                                    	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
                                                                                                    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                                                                                    	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
                                                                                                    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                                                                                    	at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:154)
                                                                                                    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                                                                                    	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
                                                                                                    	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
                                                                                                    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
                                                                                                    	at java.lang.Thread.run(Thread.java:1012)
                                                                                                    Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
                                                                                                    	at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:654)
                                                                                                    	at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:613)
                                                                                                    	at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:503)
                                                                                                    	at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:423)
                                                                                                    	at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:351)
                                                                                                    	at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
                                                                                                    	at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:90)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngineSocket$2.checkServerTrusted(ConscryptEngineSocket.java:163)
                                                                                                    	at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:256)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.verifyCertificateChain(ConscryptEngine.java:1638)

at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method)
                                                                                                    	at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
                                                                                                    	at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
                                                                                                    	... 29 more
                                                                                                    Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
                                                                                                    	... 43 more

@Mixmunity Are you using UIKIt? Can you let me know the version of UIKit?

If you are using UIKit, UIKit needs to load images itself, right? Or did you do customization for FileMessage in the message list? Can you send part of the code for which you are trying to load the message file URL with Glide?

File message doesn’t custom, Just global Glide okhttp custom.

Here’s my custom code

class CustomMessageInputComponent : MessageInputComponent() {
    companion object {
        private var leftButtonVisible = false
    }

    override fun onCreateView(
        context: Context,
        inflater: LayoutInflater,
        parent: ViewGroup,
        @Nullable args: Bundle?,
    ): View {
        params.setUseLeftButton(leftButtonVisible)
        val view = super.onCreateView(context, inflater, parent, args)
        Log.d(TAG, "onCreateView: $view")
        return view
    }

    fun setLeftButtonVisible(visible: Boolean) {
        leftButtonVisible = visible
        params.setUseLeftButton(leftButtonVisible)
    }
}

class CustomChannelFragment : ChannelFragment() {
    companion object {
        val inputComponent = CustomMessageInputComponent()
    }

    override fun onCreateModule(args: Bundle): ChannelModule {
        val module = super.onCreateModule(args)
        module.setInputComponent<MessageInputComponent>(inputComponent)
        return module
    }

    override fun onCreateViewModel(): ChannelViewModel {
        val args = if (arguments == null) Bundle() else requireArguments()
        val channelUrl = args.getString(StringSet.KEY_CHANNEL_URL, "")
        return ViewModelProvider(
            this,
            ViewModelFactory(channelUrl),
        )[channelUrl, ChannelViewModel::class.java]
    }

    fun setLeftButtonVisible(visible: Boolean) {
        inputComponent.setLeftButtonVisible(visible)
    }
}