Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rt): add support for HTTP proxies #665

Merged
merged 18 commits into from
Jun 20, 2022
Merged

feat(rt): add support for HTTP proxies #665

merged 18 commits into from
Jun 20, 2022

Conversation

aajtodd
Copy link
Contributor

@aajtodd aajtodd commented Jun 17, 2022

Issue #

closes #494

Description of changes

Adds support for common HTTP proxy setup including JVM system properties and environment variables

Does not include support for:

  • https proxies (that is proxies that use TLS, you can still use HTTPS origins by tunneling through an HTTP proxy via CONNECT request).
  • socks proxy
  • any authentication other than Basic

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@aajtodd aajtodd requested a review from a team as a code owner June 17, 2022 14:26
@aajtodd aajtodd requested review from ianbotsf and lucix-aws June 17, 2022 14:26
* # Disabling proxy selection explicitly
*
* ```
* proxySelector = ProxySelector { _ -> ProxyConfig.Direct }
Copy link
Contributor

Choose a reason for hiding this comment

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

We should really just expose this for the caller.

fun interface ProxySelector {
    fun select(url: Url): ProxyConfig
    
    companion object {
        val Direct = ProxySelector { ProxyConfig.Direct }
    }
}

val hConfig = HttpClientEngineConfig {
  proxySelector = ProxySelector.Direct
}

Comment on lines 157 to 164
private val emptyProxyList = mutableListOf<Proxy>()

internal class OkHttpProxySelector(
private val sdkSelector: SdkProxySelector
) : ProxySelector() {
override fun select(uri: URI?): MutableList<Proxy> {
if (uri == null) return emptyProxyList
val url = uri.toUrl()
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment: Returning a static/global MutableList to a caller that could modify it seems unsafe. Do we know for sure how this list is going to be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like compiler is happy with List or MutableList and intellij suggested MutableList when scaffolding the implementation and I didn't check the assumption. I will update it to use an immutable list

Comment on lines 173 to 174
}
override fun connectFailed(uri: URI?, sa: SocketAddress?, ioe: IOException?) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Missing empty line

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems like something that should be enforced by ktlint/format if we are going to go that route...

Comment on lines 139 to 155
internal interface TestEngineFactory {
/**
* Unique name for the engine
*/
val name: String

/**
* Create a new [HttpClientEngine] instance configured by [block]
*/
fun create(block: HttpClientEngineConfig.Builder.() -> Unit): HttpClientEngine
}

internal fun TestEngineFactory(name: String, configure: (HttpClientEngineConfig.Builder.() -> Unit) -> HttpClientEngine): TestEngineFactory =
object : TestEngineFactory {
override val name: String = name
override fun create(block: HttpClientEngineConfig.Builder.() -> Unit): HttpClientEngine = configure(block)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: Why not just a data class?

data class TestEngineFactory(
    val name: String,
    val configure: (HttpClientEngineConfig.Builder.() -> Unit) -> HttpClientEngine,
) {
    fun create(block: HttpClientEngineConfig.Builder.() -> Unit): HttpClientEngine = configure(block)
}

Because the last constructor arg is a function type you can still instantiate it with a lambda:

TestEngineFactory("DefaultHttpEngine") { DefaultHttpEngine(it) }

Or even more simply with a constructor reference:

TestEngineFactory("DefaultHttpEngine", ::DefaultHttpEngine)

Comment on lines 47 to 48
}
internal fun KtorOkHttpEngine(block: HttpClientEngineConfig.Builder.() -> Unit): HttpClientEngine {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Missing empty line

Comment on lines 61 to 63
proxySelector = ProxySelector { _ ->
ProxyConfig.Http("http://127.0.0.1:$proxyPort")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Unnecessary _ ->

Comment on lines 110 to 126
test { _, client ->
val req = HttpRequest {
url(Url.parse("http://aws.amazon.com"))
url.path = "/"
header("Host", "aws.amazon.com")
}

val call = client.call(req)
try {
// will be a 301 for http -> https if proxy isn't setup or not configured properly
assertEquals(HttpStatusCode.OK, call.response.status, "${client.engine}")
val body = call.response.body.readAll()!!.decodeToString()
assertEquals("hello proxy", body)
} finally {
call.complete()
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: I see a lot of duplication between this test and the one above it. Can they be refactored to use more common code?

@@ -0,0 +1,45 @@
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment: This file probably needs a copyright header just like our Kotlin files do.

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 4 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@aajtodd aajtodd merged commit 18f0524 into main Jun 20, 2022
@aajtodd aajtodd deleted the feat-proxy branch June 20, 2022 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HTTP Proxy Support
3 participants