From 5c30f201ad8dd875d98bd44f2ff5845c0d8d34cc Mon Sep 17 00:00:00 2001 From: xRain Date: Tue, 18 Aug 2026 01:29:02 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20SimApiHttpClient=20=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20stdx.net.http=E2=80=94=E2=80=94=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=20soulsoft=5Fnet=5Fhttp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - query 用 stdx.net.http ClientBuilder/HttpRequestBuilder/Client.send (等价 .NET HttpClient,替代 soulsoft_net_http.HttpClient) - TLS 配置用 stdx TlsClientConfig(TrustAll + SNI 域名) - 响应读取:status(UInt16) 2xx 判断 + InputStream 读 body - 去掉 import soulsoft_net_http - 端到端验证:stdx client 请求本机服务读响应正常 --- cjpm.lock | 24 ++++++------- src/helpers/SimApiHttpClient.cj | 62 +++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/cjpm.lock b/cjpm.lock index 468a97f..9fab0c3 100644 --- a/cjpm.lock +++ b/cjpm.lock @@ -1,20 +1,20 @@ version = 0 [requires] - soulsoft_web_http = {version = "1.0.20260528"} - soulsoft_web_cors = {version = "1.0.20260528"} - soulsoft_extensions_options_configuration = {version = "1.0.20260528"} - soulsoft_extensions_logging = {version = "1.0.20260528"} - soulsoft_web_routing = {version = "1.0.20260528"} - soulsoft_extensions_logging_console = {version = "1.0.20260528"} soulsoft_extensions_hosting = {version = "1.0.20260528"} - soulsoft_extensions_configuration = {version = "1.0.20260528"} - soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} + soulsoft_web_http = {version = "1.0.20260528"} + soulsoft_extensions_options_configuration = {version = "1.0.20260528"} + soulsoft_web_routing = {version = "1.0.20260528"} soulsoft_web_hosting = {version = "1.0.20260528"} - soulsoft_extensions_injection = {version = "1.0.20260528"} - soulsoft_net_http = {version = "1.0.20260528"} - soulsoft_extensions_options = {version = "1.0.20260528"} + soulsoft_extensions_logging = {version = "1.0.20260528"} soulsoft_web_mvc = {version = "1.0.20260528"} + soulsoft_serialization = {version = "1.0.20260528"} + soulsoft_net_http = {version = "1.0.20260528"} + soulsoft_extensions_logging_console = {version = "1.0.20260528"} soulsoft_identity_claims = {version = "1.0.20260528"} redis = {version = "1.0.20260627"} - soulsoft_serialization = {version = "1.0.20260528"} + soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} + soulsoft_extensions_configuration = {version = "1.0.20260528"} + soulsoft_extensions_options = {version = "1.0.20260528"} + soulsoft_web_cors = {version = "1.0.20260528"} + soulsoft_extensions_injection = {version = "1.0.20260528"} diff --git a/src/helpers/SimApiHttpClient.cj b/src/helpers/SimApiHttpClient.cj index 970854a..9b17337 100644 --- a/src/helpers/SimApiHttpClient.cj +++ b/src/helpers/SimApiHttpClient.cj @@ -7,10 +7,9 @@ package simapi.helpers import std.collection.* import std.io.* +import stdx.net.http.* import stdx.net.tls.* import stdx.net.tls.common.* -import soulsoft_net_http.{HttpClient, HttpRequestMessage, JsonContent} -import soulsoft_net_http.{HttpMethod as NetHttpMethod} import simapi_serialization.* import simapi.communications.* import simapi.configurations.* @@ -19,7 +18,7 @@ import simapi.exceptions.* /** * HTTP 客户端:用于调用其他带签名/AES 的 SimApi 服务。 * 对齐 C# 的 SimApi.Helpers.SimApiHttpClient: - * - 内部使用 soulsoft_net_http 的 HttpClient(等价 .NET 的 System.Net.Http.HttpClient) + * - 内部使用 stdx.net.http 的 HttpClient(等价 .NET 的 System.Net.Http.HttpClient) * - 返回泛型 T(反序列化响应 body 的 data 字段),不再返回 String * @param T 响应 data 的数据类型(任意类,simapi_serialization 反射反序列化)。 */ @@ -112,24 +111,23 @@ public open class SimApiHttpClient { * 反序列化使用 simapi_serialization(Deserialize 免约束)。 */ private func query(url: String, body: String): T { - let client = HttpClient.create { builder => - builder.noProxy() - // 支持 https:配置 TLS(信任所有证书 + SNI 域名) - var tls = TlsClientConfig() - tls.verifyMode = CertificateVerifyMode.TrustAll - let host = extractHost(url) - if (!host.isEmpty()) { - tls.serverName = Some(host) - } - builder.tlsConfig(tls) - } + let client = ClientBuilder(). + noProxy(). + tlsConfig(buildTlsConfig(url)). + readTimeout(Duration.second * 30). + build() try { - let request = HttpRequestMessage(NetHttpMethod.Post, url) - request.content = JsonContent.create(body) + let request = HttpRequestBuilder(). + post(). + url(url). + header("Content-Type", "application/json"). + body(body). + build() let response = client.send(request) try { - SimApiError.errorWhenFalse(response.isSuccessStatusCode, code: response.statusCode, message: "HTTP ERROR: ${response.statusCode}") - let json = response.content.readAsString() + SimApiError.errorWhenFalse(isSuccess(response.status), code: Int64(response.status), + message: "HTTP ERROR: ${response.status}") + let json = readBodyText(response.body) let result = JsonSerializer.Deserialize>(json) SimApiError.errorWhen(result.code != 200, code: result.code, message: result.message) return result.data.getOrThrow() @@ -141,6 +139,34 @@ public open class SimApiHttpClient { } } + /// 2xx 视为成功 + private static func isSuccess(status: UInt16): Bool { + status >= 200 && status < 300 + } + + /// 读取响应体 InputStream 为字符串 + private static func readBodyText(body: InputStream): String { + var buffer = Array(4096, repeat: 0) + var sb = StringBuilder() + var read = body.read(buffer) + while (read > 0) { + sb.appendFromUtf8(buffer.slice(0, read)) + read = body.read(buffer) + } + sb.toString() + } + + /// 构建 TLS 配置:信任所有证书 + SNI 域名 + private static func buildTlsConfig(url: String): TlsClientConfig { + var tls = TlsClientConfig() + tls.verifyMode = CertificateVerifyMode.TrustAll + let host = extractHost(url) + if (!host.isEmpty()) { + tls.serverName = Some(host) + } + tls + } + private func aesEncrypt(plain: String): String { // 对齐 C#:SimApiAesUtil.Encrypt(plain, AppKey)(AES-256-CBC + PKCS7,Base64(IV + 密文)) SimApiAesUtil.encrypt(plain, appKey)