Skip to content

Commit

Permalink
Okcurl multiplatform build (#7416)
Browse files Browse the repository at this point in the history
  • Loading branch information
yschimke committed Aug 15, 2022
1 parent 60f08a4 commit ed21bd7
Show file tree
Hide file tree
Showing 16 changed files with 539 additions and 394 deletions.
4 changes: 1 addition & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ org-conscrypt = "2.5.2"
org-jetbrains-coroutines = "1.6.4"
org-jetbrains-kotlin = "1.6.21"
org-junit-jupiter = "5.9.0"
picocli = "4.6.3"

[libraries]
amazonCorretto = "software.amazon.cryptools:AmazonCorrettoCryptoProvider:1.6.1"
Expand All @@ -27,6 +26,7 @@ bouncycastle-bcprov = { module = "org.bouncycastle:bcprov-jdk15to18", version.re
bouncycastle-bctls = { module = "org.bouncycastle:bctls-jdk15to18", version.ref = "org-bouncycastle" }
brotli-dec = "org.brotli:dec:0.1.2"
checkStyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkStyle" }
clikt = "com.github.ajalt.clikt:clikt:3.5.0"
codehaus-signature-java18 = "org.codehaus.mojo.signature:java18:1.0"
conscrypt-android = { module = "org.conscrypt:conscrypt-android", version.ref = "org-conscrypt" }
conscrypt-openjdk = { module = "org.conscrypt:conscrypt-openjdk-uber", version.ref = "org-conscrypt" }
Expand Down Expand Up @@ -70,8 +70,6 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "org-jetbrains-coroutines" }
nativeImageSvm = { module = "org.graalvm.nativeimage:svm", version.ref = "graalvm" }
openjsse = "org.openjsse:openjsse:1.1.10"
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
picocli-compiler = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
playservices-safetynet = "com.google.android.gms:play-services-safetynet:18.0.1"
robolectric-android = "org.robolectric:android-all:12.1-robolectric-8229987"
signature-android-apilevel21 = "net.sf.androidscents.signature:android-api-level-21:5.0.1_r2"
Expand Down
99 changes: 76 additions & 23 deletions okcurl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,87 @@ import com.vanniktech.maven.publish.KotlinJvm
import org.apache.tools.ant.taskdefs.condition.Os

plugins {
kotlin("jvm")
kotlin("multiplatform")
kotlin("kapt")
id("org.jetbrains.dokka")
id("com.vanniktech.maven.publish.base")
id("com.palantir.graal")
id("com.github.johnrengelman.shadow")
}

tasks.jar {
manifest {
attributes("Automatic-Module-Name" to "okhttp3.curl")
attributes("Main-Class" to "okhttp3.curl.Main")
}
}
kotlin {
jvm()

// resources-templates.
sourceSets {
main {
resources.srcDirs("$buildDir/generated/resources-templates")
}
}
sourceSets {
all {
languageSettings.optIn("kotlin.RequiresOptIn")
}

commonMain {
dependencies {
api(libs.kotlin.stdlib)
}
}

commonTest {
dependencies {
api(libs.kotlin.stdlib)
implementation(kotlin("test"))
}
}

val jvmMain by getting {
kotlin.srcDir("$buildDir/generated/resources-templates")

dependencies {
api(projects.okhttp)
api(projects.loggingInterceptor)
implementation(libs.picocli)
implementation(libs.guava.jre)
dependencies {
api(libs.kotlin.stdlib)
api(projects.okhttp)
api(projects.loggingInterceptor)
api(libs.squareup.okio)
implementation(libs.clikt)
api(libs.guava.jre)
}
}

kapt(libs.picocli.compiler)
val jvmTest by getting {
dependencies {
api(libs.kotlin.stdlib)
implementation(projects.okhttpTestingSupport)
api(libs.squareup.okio)
api(libs.assertk)
implementation(kotlin("test"))
}
}

testImplementation(projects.okhttpTestingSupport)
testImplementation(libs.junit.jupiter.api)
testImplementation(libs.assertj.core)
// Workaround for https://github.com/palantir/gradle-graal/issues/129
// Add a second configuration to populate
// runtimeClasspath vs jvmRuntimeClasspath
val main by register("main") {
dependencies {
implementation(libs.kotlin.stdlib)
implementation(projects.okhttp)
implementation(projects.loggingInterceptor)
implementation(libs.squareup.okio)
implementation(libs.clikt)
implementation(libs.guava.jre)
}
}
}
}

tasks.jar {
manifest {
attributes("Automatic-Module-Name" to "okhttp3.curl")
attributes("Main-Class" to "okhttp3.curl.MainCommandLineKt")
}
}

tasks.shadowJar {
mergeServiceFiles()
}

graal {
mainClass("okhttp3.curl.Main")
mainClass("okhttp3.curl.MainCommandLineKt")
outputName("okcurl")
graalVersion(libs.versions.graalvm.get())
javaVersion("11")
Expand All @@ -59,6 +99,18 @@ graal {
}
}

// Workaround for https://github.com/palantir/gradle-graal/issues/129
// Copy the jvmJar output into the normal jar location
val copyJvmJar = tasks.register<Copy>("copyJvmJar") {
val sourceFile = project.tasks.getByName("jvmJar").outputs.files.singleFile
val destinationFile = project.tasks.getByName("jar").outputs.files.singleFile
from(sourceFile)
into(destinationFile.parentFile)
rename (sourceFile.name, destinationFile.name)
}
tasks.getByName("copyJvmJar").dependsOn(tasks.getByName("jvmJar"))
tasks.getByName("nativeImage").dependsOn(copyJvmJar)

mavenPublishing {
configure(KotlinJvm(javadocJar = JavadocJar.Dokka("dokkaGfm")))
}
Expand All @@ -70,5 +122,6 @@ tasks.register<Copy>("copyResourcesTemplates") {
filteringCharset = Charsets.UTF_8.toString()
}.let {
tasks.processResources.dependsOn(it)
tasks.compileJava.dependsOn(it)
tasks["javaSourcesJar"].dependsOn(it)
}
46 changes: 46 additions & 0 deletions okcurl/src/commonMain/kotlin/okhttp3/curl/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2014 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.curl

import com.github.ajalt.clikt.core.CliktCommand
import okhttp3.Call
import okhttp3.Request

expect class Main() : CliktCommand {
val method: String?

val data: String?

val url: String?

val referer: String?

val headers: List<String>?

val showHeaders: Boolean

val userAgent: String

var client: Call.Factory?

override fun run()

fun createClient(): Call.Factory

fun createRequest(): Request

internal fun close()
}
101 changes: 101 additions & 0 deletions okcurl/src/commonMain/kotlin/okhttp3/curl/internal/-MainCommon.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2021 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3.curl.internal

import java.io.IOException
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.curl.Main
import okhttp3.internal.http.StatusLine
import okio.sink

internal fun Main.commonCreateRequest(): Request {
val request = Request.Builder()

val requestMethod = method ?: if (data != null) "POST" else "GET"

val url = url ?: throw IOException("No url provided")

request.url(url)

data?.let {
request.method(requestMethod, it.toRequestBody(mediaType()))
}

for (header in headers.orEmpty()) {
val parts = header.split(':', limit = 2)
if (!isSpecialHeader(parts[0])) {
request.header(parts[0], parts[1])
}
}
referer?.let {
request.header("Referer", it)
}
request.header("User-Agent", userAgent)

return request.build()
}

private fun Main.mediaType(): MediaType? {
val mimeType = headers?.let {
for (header in it) {
val parts = header.split(':', limit = 2)
if ("Content-Type".equals(parts[0], ignoreCase = true)) {
return@let parts[1].trim()
}
}
return@let null
} ?: "application/x-www-form-urlencoded"

return mimeType.toMediaTypeOrNull()
}

private fun isSpecialHeader(s: String): Boolean {
return s.equals("Content-Type", ignoreCase = true)
}

fun Main.commonRun() {
client = createClient()
val request = createRequest()

try {
val response = client!!.newCall(request).execute()
if (showHeaders) {
println(StatusLine.get(response))
val headers = response.headers
for ((name, value) in headers) {
println("$name: $value")
}
println()
}

// Stream the response to the System.out as it is returned from the server.
val out = System.out.sink()
val source = response.body.source()
while (!source.exhausted()) {
out.write(source.buffer, source.buffer.size)
out.flush()
}

response.body.close()
} catch (e: IOException) {
e.printStackTrace()
} finally {
close()
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Square, Inc.
* Copyright (C) 2014 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,11 @@
*/
package okhttp3.curl

fun main() {
Main.main(arrayOf("https://www.google.com/robots.txt"))
}
import kotlin.test.Test

class OkcurlTest {
@Test
fun simple() {
Main().main(listOf("--help"))
}
}

0 comments on commit ed21bd7

Please sign in to comment.