Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ class TestValueFactory : Closeable {
index = 0,
exchange = null,
request = call.request(),
connectTimeoutMillis = 10_000,
readTimeoutMillis = 10_000,
writeTimeoutMillis = 10_000,
client = call.client,
)

fun newRoutePlanner(
Expand Down
67 changes: 67 additions & 0 deletions okhttp/src/commonJvmAndroid/kotlin/okhttp3/Interceptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@
package okhttp3

import java.io.IOException
import java.net.Proxy
import java.net.ProxySelector
import java.util.concurrent.TimeUnit
import javax.net.SocketFactory
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.internal.tls.CertificateChainCleaner

/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
Expand Down Expand Up @@ -108,5 +115,65 @@ fun interface Interceptor {
timeout: Int,
unit: TimeUnit,
): Chain

val dns: Dns
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For provoking discussion, rather than the final set.

The advantage of Call.Decorator was we didn't need to copy all these properties.

we could

  • start out small, and add as each is shown valuable.
  • open all
  • be opinionated based on our ideas

fun withDns(dns: Dns): Chain

val socketFactory: SocketFactory

fun withSocketFactory(socketFactory: SocketFactory): Chain

val retryOnConnectionFailure: Boolean

fun withRetryOnConnectionFailure(retryOnConnectionFailure: Boolean): Chain

val authenticator: Authenticator

fun withAuthenticator(authenticator: Authenticator): Chain

val cookieJar: CookieJar

fun withCookieJar(cookieJar: CookieJar): Chain

val cache: Cache?

fun withCache(cache: Cache): Chain

val proxy: Proxy?

fun withProxy(proxy: Proxy): Chain

val proxySelector: ProxySelector

fun withProxySelector(proxySelector: ProxySelector): Chain

val proxyAuthenticator: Authenticator

fun withProxyAuthenticator(proxyAuthenticator: Authenticator): Chain

val sslSocketFactory: SSLSocketFactory

fun withSslSocketFactory(sslSocketFactory: SSLSocketFactory): Chain

val x509TrustManager: X509TrustManager?

fun withX509TrustManager(x509TrustManager: X509TrustManager): Chain

val hostnameVerifier: HostnameVerifier

fun withHostnameVerifier(hostnameVerifier: HostnameVerifier): Chain

val certificatePinner: CertificatePinner

fun withCertificatePinner(certificatePinner: CertificatePinner): Chain

val certificateChainCleaner: CertificateChainCleaner?

fun withCertificateChainCleaner(certificateChainCleaner: CertificateChainCleaner): Chain

val connectionPool: ConnectionPool

fun withConnectionPool(connectionPool: ConnectionPool): Chain
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we throw if you call this on a network interceptor, since you’re already connected?

}
}
1 change: 1 addition & 0 deletions okhttp/src/commonJvmAndroid/kotlin/okhttp3/OkHttpClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ open class OkHttpClient internal constructor(
* Creates an [Address] of out of the provided [HttpUrl]
* that uses this client’s DNS, TLS, and proxy configuration.
*/
@Deprecated("Not intended to be public API on OkHttpClient")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? I think this is out of scope for this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I'm removing the only caller, and I'm not sure we expect people to call it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a bug that it’s here. But I don’t like deprecating stuff unless we’re going to remove it later, and I definitely don’t like removing stuff later. Ultimately I believe so much in this thing that I never want to break APIs, and we should have a stronger reason to deprecate something than ‘we don’t like it anymore’.

https://www.youtube.com/watch?v=oyLBGkS5ICk

fun address(url: HttpUrl): Address {
var useSslSocketFactory: SSLSocketFactory? = null
var useHostnameVerifier: HostnameVerifier? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,7 @@ class RealCall(
index = 0,
exchange = null,
request = originalRequest,
connectTimeoutMillis = client.connectTimeoutMillis,
readTimeoutMillis = client.readTimeoutMillis,
writeTimeoutMillis = client.writeTimeoutMillis,
client = client,
)

var calledNoMoreExchanges = false
Expand Down Expand Up @@ -256,7 +254,7 @@ class RealCall(
pingIntervalMillis = client.pingIntervalMillis,
retryOnConnectionFailure = client.retryOnConnectionFailure,
fastFallback = client.fastFallback,
address = client.address(request.url),
address = chain.address(request.url),
routeDatabase = client.routeDatabase,
call = this,
request = request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,31 @@
package okhttp3.internal.http

import java.io.IOException
import java.net.Proxy
import java.net.ProxySelector
import java.util.concurrent.TimeUnit
import javax.net.SocketFactory
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Address
import okhttp3.Authenticator
import okhttp3.Cache
import okhttp3.Call
import okhttp3.CertificatePinner
import okhttp3.Connection
import okhttp3.ConnectionPool
import okhttp3.CookieJar
import okhttp3.Dns
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.internal.checkDuration
import okhttp3.internal.connection.Exchange
import okhttp3.internal.connection.RealCall
import okhttp3.internal.tls.CertificateChainCleaner

/**
* A concrete interceptor chain that carries the entire interceptor chain: all application
Expand All @@ -42,7 +58,55 @@ class RealInterceptorChain(
internal val connectTimeoutMillis: Int,
internal val readTimeoutMillis: Int,
internal val writeTimeoutMillis: Int,
override val authenticator: Authenticator,
override val cache: Cache?,
override val certificateChainCleaner: CertificateChainCleaner?,
override val certificatePinner: CertificatePinner,
override val connectionPool: ConnectionPool,
override val cookieJar: CookieJar,
override val dns: Dns,
override val hostnameVerifier: HostnameVerifier,
override val proxy: Proxy?,
override val proxyAuthenticator: Authenticator,
override val proxySelector: ProxySelector,
override val retryOnConnectionFailure: Boolean,
override val socketFactory: SocketFactory,
override val sslSocketFactory: SSLSocketFactory,
override val x509TrustManager: X509TrustManager?,
) : Interceptor.Chain {
internal constructor(
call: RealCall,
interceptors: List<Interceptor>,
index: Int,
exchange: Nothing?,
request: Request,
client: OkHttpClient,
) : this(
call,
interceptors,
index,
exchange,
request,
client.connectTimeoutMillis,
client.readTimeoutMillis,
client.writeTimeoutMillis,
client.authenticator,
client.cache,
client.certificateChainCleaner,
client.certificatePinner,
client.connectionPool,
client.cookieJar,
client.dns,
client.hostnameVerifier,
client.proxy,
client.proxyAuthenticator,
client.proxySelector,
client.retryOnConnectionFailure,
client.socketFactory,
client.sslSocketFactory,
client.x509TrustManager,
)

private var calls: Int = 0

internal fun copy(
Expand All @@ -52,6 +116,21 @@ class RealInterceptorChain(
connectTimeoutMillis: Int = this.connectTimeoutMillis,
readTimeoutMillis: Int = this.readTimeoutMillis,
writeTimeoutMillis: Int = this.writeTimeoutMillis,
authenticator: Authenticator = this.authenticator,
cache: Cache? = this.cache,
certificateChainCleaner: CertificateChainCleaner? = this.certificateChainCleaner,
certificatePinner: CertificatePinner = this.certificatePinner,
connectionPool: ConnectionPool = this.connectionPool,
cookieJar: CookieJar = this.cookieJar,
dns: Dns = this.dns,
hostnameVerifier: HostnameVerifier = this.hostnameVerifier,
proxy: Proxy? = this.proxy,
proxyAuthenticator: Authenticator = this.proxyAuthenticator,
proxySelector: ProxySelector = this.proxySelector,
retryOnConnectionFailure: Boolean = this.retryOnConnectionFailure,
socketFactory: SocketFactory = this.socketFactory,
sslSocketFactory: SSLSocketFactory = this.sslSocketFactory,
x509TrustManager: X509TrustManager? = this.x509TrustManager,
) = RealInterceptorChain(
call,
interceptors,
Expand All @@ -61,6 +140,21 @@ class RealInterceptorChain(
connectTimeoutMillis,
readTimeoutMillis,
writeTimeoutMillis,
authenticator,
cache,
certificateChainCleaner,
certificatePinner,
connectionPool,
cookieJar,
dns,
hostnameVerifier,
proxy,
proxyAuthenticator,
proxySelector,
retryOnConnectionFailure,
socketFactory,
sslSocketFactory,
x509TrustManager,
)

override fun connection(): Connection? = exchange?.connection
Expand Down Expand Up @@ -98,6 +192,96 @@ class RealInterceptorChain(
return copy(writeTimeoutMillis = checkDuration("writeTimeout", timeout.toLong(), unit))
}

override fun withDns(dns: Dns): Interceptor.Chain {
check(exchange == null) { "dns can't be adjusted in a network interceptor" }

return copy(dns = dns)
}

override fun withSocketFactory(socketFactory: SocketFactory): Interceptor.Chain {
check(exchange == null) { "socketFactory can't be adjusted in a network interceptor" }

return copy(socketFactory = socketFactory)
}

override fun withRetryOnConnectionFailure(retryOnConnectionFailure: Boolean): Interceptor.Chain {
check(exchange == null) { "retryOnConnectionFailure can't be adjusted in a network interceptor" }

return copy(retryOnConnectionFailure = retryOnConnectionFailure)
}

override fun withAuthenticator(authenticator: Authenticator): Interceptor.Chain {
check(exchange == null) { "authenticator can't be adjusted in a network interceptor" }

return copy(authenticator = authenticator)
}

override fun withCookieJar(cookieJar: CookieJar): Interceptor.Chain {
check(exchange == null) { "cookieJar can't be adjusted in a network interceptor" }

return copy(cookieJar = cookieJar)
}

override fun withCache(cache: Cache): Interceptor.Chain {
check(exchange == null) { "cache can't be adjusted in a network interceptor" }

return copy(cache = cache)
}

override fun withProxy(proxy: Proxy): Interceptor.Chain {
check(exchange == null) { "proxy can't be adjusted in a network interceptor" }

return copy(proxy = proxy)
}

override fun withProxySelector(proxySelector: ProxySelector): Interceptor.Chain {
check(exchange == null) { "proxySelector can't be adjusted in a network interceptor" }

return copy(proxySelector = proxySelector)
}

override fun withProxyAuthenticator(proxyAuthenticator: Authenticator): Interceptor.Chain {
check(exchange == null) { "proxyAuthenticator can't be adjusted in a network interceptor" }

return copy(proxyAuthenticator = proxyAuthenticator)
}

override fun withSslSocketFactory(sslSocketFactory: SSLSocketFactory): Interceptor.Chain {
check(exchange == null) { "sslSocketFactory can't be adjusted in a network interceptor" }

return copy(sslSocketFactory = sslSocketFactory)
}

override fun withX509TrustManager(x509TrustManager: X509TrustManager): Interceptor.Chain {
check(exchange == null) { "x509TrustManager can't be adjusted in a network interceptor" }

return copy(x509TrustManager = x509TrustManager)
}

override fun withHostnameVerifier(hostnameVerifier: HostnameVerifier): Interceptor.Chain {
check(exchange == null) { "hostnameVerifier can't be adjusted in a network interceptor" }

return copy(hostnameVerifier = hostnameVerifier)
}

override fun withCertificatePinner(certificatePinner: CertificatePinner): Interceptor.Chain {
check(exchange == null) { "certificatePinner can't be adjusted in a network interceptor" }

return copy(certificatePinner = certificatePinner)
}

override fun withCertificateChainCleaner(certificateChainCleaner: CertificateChainCleaner): Interceptor.Chain {
check(exchange == null) { "certificateChainCleaner can't be adjusted in a network interceptor" }

return copy(certificateChainCleaner = certificateChainCleaner)
}

override fun withConnectionPool(connectionPool: ConnectionPool): Interceptor.Chain {
check(exchange == null) { "connectionPool can't be adjusted in a network interceptor" }

return copy(connectionPool = connectionPool)
}

override fun call(): Call = call

override fun request(): Request = request
Expand Down Expand Up @@ -135,4 +319,34 @@ class RealInterceptorChain(

return response
}

/**
* Creates an [Address] of out of the provided [HttpUrl]
* that uses this client’s DNS, TLS, and proxy configuration.
*/
fun address(url: HttpUrl): Address {
var useSslSocketFactory: SSLSocketFactory? = null
var useHostnameVerifier: HostnameVerifier? = null
var useCertificatePinner: CertificatePinner? = null
if (url.isHttps) {
useSslSocketFactory = this.sslSocketFactory
useHostnameVerifier = this.hostnameVerifier
useCertificatePinner = this.certificatePinner
}

return Address(
uriHost = url.host,
uriPort = url.port,
dns = dns,
socketFactory = socketFactory,
sslSocketFactory = useSslSocketFactory,
hostnameVerifier = useHostnameVerifier,
certificatePinner = useCertificatePinner,
proxyAuthenticator = proxyAuthenticator,
proxy = proxy,
protocols = call.client.protocols,
connectionSpecs = call.client.connectionSpecs,
proxySelector = proxySelector,
)
}
}
Loading
Loading