diff --git a/buildSrc/src/main/groovy/au.com.dius.pact.kotlin-common-conventions.gradle b/buildSrc/src/main/groovy/au.com.dius.pact.kotlin-common-conventions.gradle index 7c27fc0b7..d336329a3 100644 --- a/buildSrc/src/main/groovy/au.com.dius.pact.kotlin-common-conventions.gradle +++ b/buildSrc/src/main/groovy/au.com.dius.pact.kotlin-common-conventions.gradle @@ -19,10 +19,6 @@ java { sourceCompatibility = '17' } -tasks.withType(JavaCompile).configureEach { - options.deprecation = true -} - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions { jvmTarget = "17" diff --git a/core/model/src/main/kotlin/au/com/dius/pact/core/model/PactReader.kt b/core/model/src/main/kotlin/au/com/dius/pact/core/model/PactReader.kt index de8b21d7c..4f3bf93d1 100644 --- a/core/model/src/main/kotlin/au/com/dius/pact/core/model/PactReader.kt +++ b/core/model/src/main/kotlin/au/com/dius/pact/core/model/PactReader.kt @@ -4,7 +4,6 @@ import au.com.dius.pact.core.model.messaging.MessagePact import au.com.dius.pact.core.pactbroker.PactBrokerClient import au.com.dius.pact.core.pactbroker.PactBrokerClientConfig import au.com.dius.pact.core.pactbroker.PactBrokerResult -import au.com.dius.pact.core.support.Auth import au.com.dius.pact.core.support.HttpClient import au.com.dius.pact.core.support.HttpClientUtils import au.com.dius.pact.core.support.HttpClientUtils.isJsonResponse @@ -20,18 +19,10 @@ import au.com.dius.pact.core.support.json.map import au.com.dius.pact.core.support.jsonArray import au.com.dius.pact.core.support.jsonObject import io.github.oshai.kotlinlogging.KotlinLogging -import org.apache.hc.client5.http.auth.AuthScope -import org.apache.hc.client5.http.auth.UsernamePasswordCredentials import org.apache.hc.client5.http.classic.methods.HttpGet -import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy -import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider import org.apache.hc.client5.http.impl.classic.CloseableHttpClient -import org.apache.hc.client5.http.impl.classic.HttpClientBuilder -import org.apache.hc.client5.http.impl.classic.HttpClients import org.apache.hc.core5.http.ContentType import org.apache.hc.core5.http.io.entity.EntityUtils -import org.apache.hc.core5.http.message.BasicHeader -import org.apache.hc.core5.util.TimeValue import java.io.File import java.io.InputStream import java.io.InputStreamReader @@ -103,51 +94,6 @@ fun fetchJsonResource(http: CloseableHttpClient, source: UrlPactSource): } } -@Deprecated("Use HttpClient.newHttpClient instead") -fun newHttpClient(baseUrl: String, options: Map): CloseableHttpClient { - val builder = HttpClients.custom().useSystemProperties() - .setRetryStrategy(DefaultHttpRequestRetryStrategy(5, TimeValue.ofMilliseconds(3000))) - - when { - options["authentication"] is Auth -> { - when (val auth = options["authentication"] as Auth) { - is Auth.BasicAuthentication -> basicAuth(baseUrl, auth.username, auth.password, builder) - is Auth.BearerAuthentication -> { - builder.setDefaultHeaders(listOf(BasicHeader(auth.headerName, "Bearer " + auth.token))) - } - else -> {} - } - } - options["authentication"] is List<*> -> { - val authentication = options["authentication"] as List<*> - when (val scheme = authentication.first().toString().lowercase(Locale.getDefault())) { - "basic" -> { - if (authentication.size > 2) { - basicAuth(baseUrl, authentication[1].toString(), authentication[2].toString(), builder) - } else { - logger.warn { "Basic authentication requires a username and password, ignoring." } - } - } - else -> logger.warn { "Only supports basic authentication, got '$scheme', ignoring." } - } - } - options.containsKey("authentication") -> { - logger.warn { "Authentication options needs to be a Auth class or a list of values, " + - "got '${options["authentication"]}', ignoring." } - } - } - - return builder.build() -} - -private fun basicAuth(baseUrl: String, username: String, password: String, builder: HttpClientBuilder) { - val credsProvider = BasicCredentialsProvider() - val uri = URI(baseUrl) - credsProvider.setCredentials(AuthScope(uri.host, uri.port), - UsernamePasswordCredentials(username, password.toCharArray())) - builder.setDefaultCredentialsProvider(credsProvider) -} - /** * Parses the query string into a Map */ @@ -383,7 +329,7 @@ object DefaultPactReader : PactReader { when (k) { "responseMatchingRules" -> "matchingRules" to v "requestMatchingRules" -> "matchingRules" to v - "method" -> "method" to Json.toString(v).toUpperCase() + "method" -> "method" to Json.toString(v).uppercase(Locale.getDefault()) else -> k to v } }) @@ -420,10 +366,10 @@ object DefaultPactReader : PactReader { } } else if (source is URL || source is UrlPactSource) { val urlSource = if (source is URL) UrlSource(source.toString()) else source as UrlPactSource - return loadPactFromUrl(urlSource, options, newHttpClient(urlSource.url, options)) + return loadPactFromUrl(urlSource, options, HttpClient.newHttpClient(options["authentication"], URI(urlSource.url)).first) } else if (source is String && source.lowercase(Locale.getDefault()).matches(Regex("(https?|file)://?.*"))) { val urlSource = UrlSource(source) - return loadPactFromUrl(urlSource, options, newHttpClient(urlSource.url, options)) + return loadPactFromUrl(urlSource, options, HttpClient.newHttpClient(options["authentication"], URI(urlSource.url)).first) } else if (source is String && source.lowercase(Locale.getDefault()).matches(Regex("s3://.*"))) { return loadPactFromS3Bucket(source) } else if (source is String && source.startsWith(CLASSPATH_URI_START)) { diff --git a/core/model/src/test/groovy/au/com/dius/pact/core/model/PactReaderSpec.groovy b/core/model/src/test/groovy/au/com/dius/pact/core/model/PactReaderSpec.groovy index 65ddf7d2c..eb9f17a10 100644 --- a/core/model/src/test/groovy/au/com/dius/pact/core/model/PactReaderSpec.groovy +++ b/core/model/src/test/groovy/au/com/dius/pact/core/model/PactReaderSpec.groovy @@ -11,9 +11,6 @@ import au.com.dius.pact.core.support.json.JsonParser import com.amazonaws.services.s3.AmazonS3 import com.amazonaws.services.s3.model.S3Object import com.amazonaws.services.s3.model.S3ObjectInputStream -import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider -import org.apache.hc.client5.http.impl.classic.RedirectExec -import org.apache.hc.client5.http.protocol.RedirectStrategy import spock.lang.Issue import spock.lang.Specification import spock.lang.Unroll @@ -183,33 +180,6 @@ class PactReaderSpec extends Specification { pact.metadata == [pactSpecification: [version: '2.0.0'], 'pact-jvm': [version: '']] } - @SuppressWarnings('UnnecessaryGetter') - def 'if authentication is set, sets up the http client with auth'() { - given: - def pactUrl = new UrlSource('http://url.that.requires.auth:8080/') - - when: - def client = PactReaderKt.newHttpClient(pactUrl.url, [authentication: ['basic', 'user', 'pwd']]) - def creds = client.credentialsProvider.credMap.entrySet().first().getValue() - - then: - client.credentialsProvider instanceof BasicCredentialsProvider - creds.principal.username == 'user' - creds.password == 'pwd'.toCharArray() - } - - def 'custom retry strategy is added to execution chain of client'() { - given: - def pactUrl = new UrlSource('http://some.url/') - - when: - def client = PactReaderKt.newHttpClient(pactUrl.url, [:]) - - then: - client.execChain.handler instanceof RedirectExec - client.execChain.handler.redirectStrategy instanceof RedirectStrategy - } - def 'correctly loads V2 pact query strings'() { given: def pactUrl = PactReaderSpec.classLoader.getResource('v2_pact_query.json') diff --git a/core/support/src/test/groovy/au/com/dius/pact/core/support/HttpClientSpec.groovy b/core/support/src/test/groovy/au/com/dius/pact/core/support/HttpClientSpec.groovy index a7f9be987..dcacb060b 100644 --- a/core/support/src/test/groovy/au/com/dius/pact/core/support/HttpClientSpec.groovy +++ b/core/support/src/test/groovy/au/com/dius/pact/core/support/HttpClientSpec.groovy @@ -1,5 +1,7 @@ package au.com.dius.pact.core.support +import org.apache.hc.client5.http.auth.AuthScope +import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider import org.apache.hc.client5.http.impl.classic.HttpRequestRetryExec import org.apache.hc.client5.http.impl.classic.MainClientExec import org.apache.hc.client5.http.protocol.RequestDefaultHeaders @@ -55,4 +57,21 @@ class HttpClientSpec extends Specification { where: method << Method.values() } + + @SuppressWarnings('UnnecessaryGetter') + def 'if authentication is set, sets up the http client with auth'() { + given: + URI uri = new URI('http://localhost') + def authentication = ['basic', 'user', 'pwd'] + def authScope = new AuthScope(uri.host, uri.port) + + when: + def client = HttpClient.INSTANCE.newHttpClient(authentication, uri, 1, 1, false) + def creds = client.second.getCredentials(authScope, null) + + then: + client.second instanceof SystemDefaultCredentialsProvider + creds.principal.username == 'user' + creds.password == 'pwd'.toCharArray() + } }