From 6052adebd9c41edf7a44e77abdeb5ed01a526e8c Mon Sep 17 00:00:00 2001 From: tursom <tursom@foxmail.com> Date: Wed, 10 Jan 2024 23:50:57 +0800 Subject: [PATCH] add ts-core/ts-http --- build.gradle.kts | 6 +- gradle.properties | 2 +- settings.gradle.kts | 1 + .../kotlin/cn/tursom/core/util/concurrent.kt | 42 +++ ts-core/ts-http/README.md | 25 ++ ts-core/ts-http/build.gradle.kts | 6 + .../cn/tursom/http/client/OkHttpDelete.kt | 112 ++++++++ .../kotlin/cn/tursom/http/client/OkHttpGet.kt | 30 +++ .../cn/tursom/http/client/OkHttpPatch.kt | 239 +++++++++++++++++ .../cn/tursom/http/client/OkHttpPost.kt | 152 +++++++++++ .../kotlin/cn/tursom/http/client/OkHttpPut.kt | 240 ++++++++++++++++++ .../kotlin/cn/tursom/http/client/okhttp.kt | 105 ++++++++ .../test/kotlin/cn/tursom/proxy/Example.kt | 2 +- .../kotlin/cn/tursom/gradle/PublishPlugin.kt | 6 - .../kotlin/cn/tursom/gradle/Dependencies.kt | 10 + 15 files changed, 967 insertions(+), 11 deletions(-) create mode 100644 ts-core/src/main/kotlin/cn/tursom/core/util/concurrent.kt create mode 100644 ts-core/ts-http/README.md create mode 100644 ts-core/ts-http/build.gradle.kts create mode 100644 ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpDelete.kt create mode 100644 ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpGet.kt create mode 100644 ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPatch.kt create mode 100644 ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPost.kt create mode 100644 ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPut.kt create mode 100644 ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/okhttp.kt diff --git a/build.gradle.kts b/build.gradle.kts index 72a51e3..47cfc1e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,9 @@ plugins { } allprojects { + group = "cn.tursom" + version = "1.1-SNAPSHOT" + apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "maven-publish") apply(plugin = "ts-gradle-env") @@ -21,9 +24,6 @@ allprojects { apply(plugin = "ts-gradle-publish") apply(plugin = "ts-gradle-repos") - group = "cn.tursom" - version = "1.1-SNAPSHOT" - tasks.withType<KotlinCompile>().configureEach { kotlinOptions.jvmTarget = "21" kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" diff --git a/gradle.properties b/gradle.properties index c436ebe..e44792b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,4 +21,4 @@ android.enableJetifier=true kotlin.code.style=official project.groupId=cn.tursom -project.version=1.0-SNAPSHOT +project.version=1.1-SNAPSHOT diff --git a/settings.gradle.kts b/settings.gradle.kts index 2f9bdf3..47c530b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ include("ts-core:ts-yaml") include("ts-core:ts-json") include("ts-core:ts-xml") include("ts-core:ts-async-http") +include("ts-core:ts-http") include("ts-core:ts-proxy") include("ts-core:ts-proxy-jdk") include("ts-core:ts-reflect") diff --git a/ts-core/src/main/kotlin/cn/tursom/core/util/concurrent.kt b/ts-core/src/main/kotlin/cn/tursom/core/util/concurrent.kt new file mode 100644 index 0000000..d4a8c16 --- /dev/null +++ b/ts-core/src/main/kotlin/cn/tursom/core/util/concurrent.kt @@ -0,0 +1,42 @@ +package cn.tursom.core.util + +import java.util.concurrent.CompletableFuture +import java.util.concurrent.TimeUnit + +inline fun <V> withFuture(callback: (future: CompletableFuture<V>) -> Unit): V { + val future = CompletableFuture<V>() + callback(future) + return future.get() +} + +inline fun <V> withFuture( + timeout: Long, + timeUnit: TimeUnit, + callback: (future: CompletableFuture<V>) -> Unit, +): V { + val future = CompletableFuture<V>() + callback(future) + return future.get(timeout, timeUnit) +} + +fun <R> withTimeout( + timeout: Long, + timeUnit: TimeUnit, + callback: () -> R, +): R { + val future = CompletableFuture<R>() + + val execThread = Thread.ofVirtual() + .start { + future.complete(callback()) + } + + try { + return future.get(timeout, timeUnit) + } catch (t: Throwable) { + execThread.interrupt() + future.cancel(true) + + throw t + } +} diff --git a/ts-core/ts-http/README.md b/ts-core/ts-http/README.md new file mode 100644 index 0000000..1df1faf --- /dev/null +++ b/ts-core/ts-http/README.md @@ -0,0 +1,25 @@ +# ts-http 模块 +## 简介 +ts-http 模块负责提供同步的 http 请求接口。目前我们仅对 OkHttp 进行了少量封装,以提高易用性。 + +封装的功能包括: +1. DSL 支持。DSL 形式的请求构建结构更加清晰,易于维护。 +2. json 解析。这部分需要引入 GSON 依赖。 +3. 其他接口封装。如 Call.str()、Call.bytes() 等。 + +## 功能描述 +### DSL 支持 +ts-http 模块提供轻量级的 DSL 封装。提供的方法有: +- ```Call.Factory.newCall(builder: Request.Builder.() -> Unit): Call``` 用于构建新请求 +- ```WebSocket.Factory.newWebSocket(listener: WebSocketListener, builder: Request.Builder.() -> Unit): WebSocket``` 用于构建 WebSocket 请求 +- ```<B : Request.Builder> B.url(url: String? = null, builder: HttpUrl.Builder.() -> Unit): B``` 用于构建请求 url +- ```form(builder: FormBody.Builder.() -> Unit): FormBody``` 用于构建 form 请求体 +- ```FormBody.Builder.build(builder: FormBody.Builder.() -> Unit): FormBody``` 同上 + +### json 解析 +ts-http 模块使用 GSON 提供 json 解析功能,考虑到有些项目可能不希望引入 GSON 依赖,因此没有自动引入 GSON。用户如果希望使用此功能,需要手动引入 GSON 依赖。由于 ts-http 只使用了 GSON 最基础的功能,因此对 GSON 的版本没有过高要求,只要有```T fromJson(String json, Class<T> classOfT)```,```T fromJson(String json, Type typeOfT)```和```com.google.gson.reflect.TypeToken<T>```即可。 + +ts-http 为 Call 和 ResponseBody 分别添加了```inline fun <reified T : Any> json(): T```和```inline fun <reified T : Any> jsonTyped(): T```这两个方法,前者直接使用```T::class.java```获取 Class 对象,后者则使用 TypeToken 获取 Type 对象,用户可以根据需求使用不同的方法。 + +### 其他接口封装 +ts-http 还为 GET 和 POST 单独封装了额外的接口以便于使用。 diff --git a/ts-core/ts-http/build.gradle.kts b/ts-core/ts-http/build.gradle.kts new file mode 100644 index 0000000..26ad97f --- /dev/null +++ b/ts-core/ts-http/build.gradle.kts @@ -0,0 +1,6 @@ +dependencies { + api(project(":")) + api(project(":ts-core")) + api(group = "com.squareup.okhttp3", name = "okhttp", version = "4.12.0") + compileOnly(group = "io.netty", name = "netty-all", version = nettyVersion) +} diff --git a/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpDelete.kt b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpDelete.kt new file mode 100644 index 0000000..411d56a --- /dev/null +++ b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpDelete.kt @@ -0,0 +1,112 @@ +package cn.tursom.http.client + +import okhttp3.Call +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import java.io.File + +@JvmOverloads +@OkhttpMaker +inline fun Call.Factory.delete( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): Response = newCall { + delete(body()) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.delete( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): Response = newCall { + delete(body) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.delete( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): Response = delete(url, headers) { + form { + add(param) + } +} + +@JvmOverloads +fun Call.Factory.delete( + url: String, + body: String, + headers: Map<String, String>? = null, +) = delete(url, headers) { + body.toRequestBody() +} + +@JvmOverloads +fun Call.Factory.delete( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +) = delete(url, headers) { + body.toRequestBody() +} + +@JvmOverloads +fun Call.Factory.delete( + url: String, + body: File, + headers: Map<String, String>? = null, +) = delete(url, headers) { + body.asRequestBody() +} + +@JvmOverloads +fun Call.Factory.delete( + url: String, + param: Map<String, String?>? = null, + headers: Map<String, String>? = null, +): Response = newCall { + url(url) { + addQueryParameters(param) + } + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.deleteStr( + url: String, + param: Map<String, String>? = null, + headers: Map<String, String>? = null, +): String = delete(url, param, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.deleteByteArray( + url: String, + param: Map<String, String>? = null, + headers: Map<String, String>? = null, +): ByteArray = delete(url, param, headers).body!!.bytes() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.deleteJson( + url: String, + param: Map<String, String>? = null, + headers: Map<String, String>? = null, +): String = delete(url, param, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.deleteJsonTyped( + url: String, + param: Map<String, String>? = null, + headers: Map<String, String>? = null, +): T = delete(url, param, headers).body!!.jsonTyped() + + diff --git a/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpGet.kt b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpGet.kt new file mode 100644 index 0000000..df42d73 --- /dev/null +++ b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpGet.kt @@ -0,0 +1,30 @@ +package cn.tursom.http.client + +import okhttp3.Call +import okhttp3.Response + +@JvmOverloads +fun Call.Factory.get( + url: String, + param: Map<String, String?>? = null, + headers: Map<String, String>? = null, +): Response = newCall { + url(url) { + addQueryParameters(param) + } + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.getStr( + url: String, + param: Map<String, String>? = null, + headers: Map<String, String>? = null, +): String = get(url, param, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.getByteArray( + url: String, + param: Map<String, String>? = null, + headers: Map<String, String>? = null, +): ByteArray = get(url, param, headers).body!!.bytes() diff --git a/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPatch.kt b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPatch.kt new file mode 100644 index 0000000..2f4bdd8 --- /dev/null +++ b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPatch.kt @@ -0,0 +1,239 @@ +package cn.tursom.http.client + +import okhttp3.Call +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import java.io.File + +@JvmOverloads +@OkhttpMaker +inline fun Call.Factory.patch( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): Response = newCall { + put(body()) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.patch( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): Response = newCall { + put(body) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.patch( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): Response = patch(url, headers) { + form { + add(param) + } +} + +@JvmOverloads +fun Call.Factory.patch( + url: String, + body: String, + headers: Map<String, String>? = null, +) = patch(url, headers) { + body.toRequestBody() +} + +@JvmOverloads +fun Call.Factory.patch( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +) = patch(url, headers) { + body.toRequestBody() +} + +@JvmOverloads +fun Call.Factory.patch( + url: String, + body: File, + headers: Map<String, String>? = null, +) = patch(url, headers) { + body.asRequestBody() +} + +@JvmOverloads +fun Call.Factory.patchStr( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): String = patch(url, headers, body).body!!.string() + +@JvmOverloads +fun Call.Factory.patchStr( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): String = patch(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.patchStr( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): String = patch(url, param, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.patchStr( + url: String, + body: String, + headers: Map<String, String>? = null, +): String = patch(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.patchStr( + url: String, + body: File, + headers: Map<String, String>? = null, +): String = patch(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.patchStr( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): String = patch(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.patchBytes( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): ByteArray = patch(url, headers, body).body!!.bytes() + +@JvmOverloads +fun Call.Factory.patchBytes( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): ByteArray = patch(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.patchBytes( + url: String, + body: String, + headers: Map<String, String>? = null, +): ByteArray = patch(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.patchBytes( + url: String, + body: File, + headers: Map<String, String>? = null, +): ByteArray = patch(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.patchBytes( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): ByteArray = patch(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.patchBytes( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): ByteArray = patch(url, param, headers).body!!.bytes() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJson( + url: String, + json: String, + headers: Map<String, String>? = null, +): T = patch(url, json, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJson( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): T = patch(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJson( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): T = patch(url, param, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJson( + url: String, + body: File, + headers: Map<String, String>? = null, +): T = patch(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJson( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): T = patch(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJson( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): T = patch(url, headers, body).body!!.json() + +// patchJsonTyped +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJsonTyped( + url: String, + json: String, + headers: Map<String, String>? = null, +): T = patch(url, json, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJsonTyped( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): T = patch(url, body, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJsonTyped( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): T = patch(url, param, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJsonTyped( + url: String, + body: File, + headers: Map<String, String>? = null, +): T = patch(url, body, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJsonTyped( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): T = patch(url, body, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.patchJsonTyped( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): T = patch(url, headers, body).body!!.jsonTyped() diff --git a/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPost.kt b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPost.kt new file mode 100644 index 0000000..0755b2e --- /dev/null +++ b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPost.kt @@ -0,0 +1,152 @@ +package cn.tursom.http.client + +import okhttp3.* +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import java.io.File + +@JvmOverloads +@OkhttpMaker +inline fun Call.Factory.post( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): Response = newCall { + post(body()) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.post( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): Response = newCall { + post(body) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.post( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): Response = post(url, headers) { + form { + add(param) + } +} + +@JvmOverloads +fun Call.Factory.post( + url: String, + body: String, + headers: Map<String, String>? = null, +) = post(url, headers) { + body.toRequestBody("text/plain;charset=utf-8".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.post( + url: String, + body: File, + headers: Map<String, String>? = null, +) = post(url, headers) { + body.asRequestBody("application/octet-stream".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.post( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +) = post(url, headers) { + body.toRequestBody("application/octet-stream".toMediaTypeOrNull()) +} + +@JvmOverloads +@OkhttpMaker +inline fun Call.Factory.postStr( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): String = post(url, headers, body).body!!.string() + +@JvmOverloads +fun Call.Factory.postStr( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): String = post(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.postStr( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): String = postStr(url, headers) { + FormBody.Builder().add(param).build() +} + +@JvmOverloads +fun Call.Factory.postStr( + url: String, + body: String, + headers: Map<String, String>? = null, +): String = postStr(url, headers) { + body.toRequestBody("text/plain;charset=utf-8".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.postStr( + url: String, + body: File, + headers: Map<String, String>? = null, +): String = postStr(url, headers) { + body.asRequestBody("application/octet-stream".toMediaTypeOrNull()) +} + +@JvmOverloads +@OkhttpMaker +inline fun Call.Factory.postByteArray( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): ByteArray = post(url, headers, body).body!!.bytes() + +@JvmOverloads +fun Call.Factory.postByteArray( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): ByteArray = post(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.postByteArray( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): ByteArray = postByteArray(url, headers) { + FormBody.Builder().add(param).build() +} + +@JvmOverloads +fun Call.Factory.postByteArray( + url: String, + body: String, + headers: Map<String, String>? = null, +): ByteArray = postByteArray(url, headers) { + body.toRequestBody("text/plain;charset=utf-8".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.postByteArray( + url: String, + body: File, + headers: Map<String, String>? = null, +): ByteArray = postByteArray(url, headers) { + body.asRequestBody("application/octet-stream".toMediaTypeOrNull()) +} diff --git a/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPut.kt b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPut.kt new file mode 100644 index 0000000..30fefe5 --- /dev/null +++ b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/OkHttpPut.kt @@ -0,0 +1,240 @@ +package cn.tursom.http.client; + +import okhttp3.Call +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import java.io.File +import kotlin.jvm.JvmOverloads; + +@JvmOverloads +@OkhttpMaker +inline fun Call.Factory.put( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): Response = newCall { + put(body()) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.put( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): Response = newCall { + put(body) + url(url) + addHeaders(headers) +}.execute() + +@JvmOverloads +fun Call.Factory.put( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): Response = put(url, headers) { + form { + add(param) + } +} + +@JvmOverloads +fun Call.Factory.put( + url: String, + body: String, + headers: Map<String, String>? = null, +) = put(url, headers) { + body.toRequestBody("text/plain;charset=utf-8".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.put( + url: String, + body: File, + headers: Map<String, String>? = null, +) = put(url, headers) { + body.asRequestBody("application/octet-stream".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.put( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +) = put(url, headers) { + body.toRequestBody("application/octet-stream".toMediaTypeOrNull()) +} + +@JvmOverloads +fun Call.Factory.putStr( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): String = put(url, headers, body).body!!.string() + +@JvmOverloads +fun Call.Factory.putStr( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): String = put(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.putStr( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): String = put(url, param, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.putStr( + url: String, + body: String, + headers: Map<String, String>? = null, +): String = put(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.putStr( + url: String, + body: File, + headers: Map<String, String>? = null, +): String = put(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.putStr( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): String = put(url, body, headers).body!!.string() + +@JvmOverloads +fun Call.Factory.putBytes( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): ByteArray = put(url, headers, body).body!!.bytes() + +@JvmOverloads +fun Call.Factory.putBytes( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): ByteArray = put(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.putBytes( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): ByteArray = put(url, param, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.putBytes( + url: String, + body: String, + headers: Map<String, String>? = null, +): ByteArray = put(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.putBytes( + url: String, + body: File, + headers: Map<String, String>? = null, +): ByteArray = put(url, body, headers).body!!.bytes() + +@JvmOverloads +fun Call.Factory.putBytes( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): ByteArray = put(url, body, headers).body!!.bytes() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJson( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): T = put(url, headers, body).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJson( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJson( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): T = put(url, param, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJson( + url: String, + body: String, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJson( + url: String, + body: File, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJson( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.json() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJsonTyped( + url: String, + headers: Map<String, String>? = null, + body: Request.Builder.() -> RequestBody, +): T = put(url, headers, body).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJsonTyped( + url: String, + body: RequestBody, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJsonTyped( + url: String, + param: Map<String, String>, + headers: Map<String, String>? = null, +): T = put(url, param, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJsonTyped( + url: String, + body: String, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJsonTyped( + url: String, + body: File, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.jsonTyped() + +@JvmOverloads +inline fun <reified T : Any> Call.Factory.putJsonTyped( + url: String, + body: ByteArray, + headers: Map<String, String>? = null, +): T = put(url, body, headers).body!!.jsonTyped() diff --git a/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/okhttp.kt b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/okhttp.kt new file mode 100644 index 0000000..42bbd76 --- /dev/null +++ b/ts-core/ts-http/src/main/kotlin/cn/tursom/http/client/okhttp.kt @@ -0,0 +1,105 @@ +@file:Suppress("unused") + +package cn.tursom.http.client + +import cn.tursom.core.util.Utils.gson +import cn.tursom.core.util.fromJson +import cn.tursom.core.util.fromJsonTyped +import okhttp3.* +import okhttp3.HttpUrl.Companion.toHttpUrl +import java.net.InetSocketAddress +import java.net.Proxy +import java.net.SocketAddress + +@DslMarker +@Retention(AnnotationRetention.BINARY) +annotation class OkhttpMaker + +@OkhttpMaker +object Okhttp : Call.Factory, WebSocket.Factory { + val direct: OkHttpClient = OkHttpClient().newBuilder() + .retryOnConnectionFailure(true) + .build() + val socket: OkHttpClient = proxy() + + var default: OkHttpClient = direct + + override fun newCall(request: Request): Call = default.newCall(request) + override fun newWebSocket(request: Request, listener: WebSocketListener): WebSocket = + default.newWebSocket(request, listener) + + @JvmOverloads + fun proxy( + host: String = "127.0.0.1", + port: Int = 1080, + type: Proxy.Type = Proxy.Type.SOCKS, + builder: OkHttpClient.Builder = OkHttpClient().newBuilder(), + ): OkHttpClient = builder + .proxy(Proxy(type, InetSocketAddress(host, port) as SocketAddress)) + .retryOnConnectionFailure(true) + .build() +} + +@OkhttpMaker +inline fun <B : Request.Builder> B.url( + url: String? = null, + builder: HttpUrl.Builder.() -> Unit, +): B = apply { + val urlBuilder = url?.toHttpUrl()?.newBuilder() ?: HttpUrl.Builder() + + urlBuilder.builder() + url(urlBuilder.build()) +} + +fun <B : Request.Builder> B.addHeaders(headers: Map<String, String>?): B = apply { + headers?.forEach { (k, v) -> + addHeader(k, v) + } +} + +@OkhttpMaker +inline fun form(builder: FormBody.Builder.() -> Unit): FormBody = + FormBody.Builder().build(builder) + +fun HttpUrl.Builder.addQueryParameters(params: Map<String, String?>?) { + params?.forEach { (k, v) -> + addQueryParameter(k, v) + } +} + +@OkhttpMaker +inline infix fun FormBody.Builder.build(builder: FormBody.Builder.() -> Unit): FormBody { + val form = FormBody.Builder() + form.builder() + return form.build() +} + +fun FormBody.Builder.add(forms: Map<String, String>?) = apply { + forms?.forEach { (k, v) -> + add(k, v) + } +} + +fun FormBody.Builder.addEncoded(forms: Map<String, String>?) = apply { + forms?.forEach { (k, v) -> + addEncoded(k, v) + } +} + +fun Call.str() = execute().body!!.string() +fun Call.bytes() = execute().body!!.bytes() +inline fun <reified T : Any> Call.json(): T = execute().body!!.json<T>() +inline fun <reified T : Any> Call.jsonTyped(): T = execute().body!!.jsonTyped<T>() + +@OkhttpMaker +inline fun WebSocket.Factory.newWebSocket( + listener: WebSocketListener, + builder: Request.Builder.() -> Unit, +): WebSocket = newWebSocket(Request.Builder().apply(builder).build(), listener) + +@OkhttpMaker +inline fun Call.Factory.newCall(builder: Request.Builder.() -> Unit) = + newCall(Request.Builder().apply(builder).build()) + +inline fun <reified T : Any> ResponseBody.json(): T = gson.fromJson<T>(string()) +inline fun <reified T : Any> ResponseBody.jsonTyped(): T = gson.fromJsonTyped<T>(string()) diff --git a/ts-core/ts-proxy/src/test/kotlin/cn/tursom/proxy/Example.kt b/ts-core/ts-proxy/src/test/kotlin/cn/tursom/proxy/Example.kt index e26ca98..5939755 100644 --- a/ts-core/ts-proxy/src/test/kotlin/cn/tursom/proxy/Example.kt +++ b/ts-core/ts-proxy/src/test/kotlin/cn/tursom/proxy/Example.kt @@ -83,7 +83,7 @@ class Example { @Test fun benchmark() { - val (t, container) = Proxy.get<TestClass>() + val (t, container) = Proxy.get<TestClass>(useDirectAccessor = true) container.addProxy(GetA(t)) println(t.javaClass) diff --git a/ts-gradle/ts-gradle-publish/src/main/kotlin/cn/tursom/gradle/PublishPlugin.kt b/ts-gradle/ts-gradle-publish/src/main/kotlin/cn/tursom/gradle/PublishPlugin.kt index 117227e..f5e96a8 100644 --- a/ts-gradle/ts-gradle-publish/src/main/kotlin/cn/tursom/gradle/PublishPlugin.kt +++ b/ts-gradle/ts-gradle-publish/src/main/kotlin/cn/tursom/gradle/PublishPlugin.kt @@ -51,12 +51,6 @@ private fun Project.createTursomPublishRepository(repositoryHandler: RepositoryH uri("https://jmp.mvn.tursom.cn:20080/repository/maven-releases/") } - repository.authentication{ ac -> - ac.forEach { - - } - } - repository.credentials(PasswordCredentials::class.java) { credentials -> val artifactoryUser: String = rootProject.ext["tursom.artifactoryUser"]!!.toString() val artifactoryPassword: String = rootProject.ext["tursom.artifactoryPassword"]!!.toString() diff --git a/ts-gradle/ts-gradle-repos/src/main/kotlin/cn/tursom/gradle/Dependencies.kt b/ts-gradle/ts-gradle-repos/src/main/kotlin/cn/tursom/gradle/Dependencies.kt index 9ce99c7..c53cdfa 100644 --- a/ts-gradle/ts-gradle-repos/src/main/kotlin/cn/tursom/gradle/Dependencies.kt +++ b/ts-gradle/ts-gradle-repos/src/main/kotlin/cn/tursom/gradle/Dependencies.kt @@ -123,6 +123,7 @@ val DependencyHandler.`ts-delegation` get() = tursomServer("ts-delegation") val DependencyHandler.`ts-observer` get() = tursomServer("ts-observer") val DependencyHandler.`ts-encrypt` get() = tursomServer("ts-encrypt") val DependencyHandler.`ts-hash` get() = tursomServer("ts-hash") +val DependencyHandler.`ts-http` get() = tursomServer("ts-http") val DependencyHandler.`ts-json` get() = tursomServer("ts-json") val DependencyHandler.`ts-log` get() = tursomServer("ts-log") val DependencyHandler.`ts-mail` get() = tursomServer("ts-mail") @@ -192,6 +193,10 @@ fun DependencyHandler.`ts-hash`( dependencyConfiguration: Action<ExternalModuleDependency>? = null ) = tursomServer("ts-hash", dependencyConfiguration = dependencyConfiguration) +fun DependencyHandler.`ts-http`( + dependencyConfiguration: Action<ExternalModuleDependency>? = null +) = tursomServer("ts-http", dependencyConfiguration = dependencyConfiguration) + fun DependencyHandler.`ts-json`( dependencyConfiguration: Action<ExternalModuleDependency>? = null ) = tursomServer("ts-json", dependencyConfiguration = dependencyConfiguration) @@ -284,6 +289,7 @@ val DependencyHandler.ts_delegation get() = tursomServer("ts-delegation") val DependencyHandler.ts_observer get() = tursomServer("ts-observer") val DependencyHandler.ts_encrypt get() = tursomServer("ts-encrypt") val DependencyHandler.ts_hash get() = tursomServer("ts-hash") +val DependencyHandler.ts_http get() = tursomServer("ts-http") val DependencyHandler.ts_json get() = tursomServer("ts-json") val DependencyHandler.ts_log get() = tursomServer("ts-log") val DependencyHandler.ts_mail get() = tursomServer("ts-mail") @@ -353,6 +359,10 @@ fun DependencyHandler.ts_hash( dependencyConfiguration: Action<ExternalModuleDependency>? = null ) = tursomServer("ts-hash", dependencyConfiguration = dependencyConfiguration) +fun DependencyHandler.ts_http( + dependencyConfiguration: Action<ExternalModuleDependency>? = null +) = tursomServer("ts-http", dependencyConfiguration = dependencyConfiguration) + fun DependencyHandler.ts_json( dependencyConfiguration: Action<ExternalModuleDependency>? = null ) = tursomServer("ts-json", dependencyConfiguration = dependencyConfiguration)