ntroduce separate HttpClient instances for raw and compressed HTTP transfer modes

Added two HttpClient instances to distinguish between legacy (no
Accept-Encoding) and modern compressed HTTP transfer behaviors.

- LegacyHttp:
  Sends no Accept-Encoding header.
  Used when requesting .dll.gz files, ensuring that the server delivers
  the file exactly as-is without applying HTTP-level compression.

- Http:
  Enables AutomaticDecompression and advertises Accept-Encoding
  (gzip, deflate).
  When the server supports HTTP content compression, even a regular .dll
  file can be transmitted in compressed form and transparently
  decompressed by the client.

This separation prevents ambiguities between:
  - File-level compression (.dll.gz)
  - Transport-level compression (Content-Encoding: gzip/deflate)

and ensures predictable behavior when downloading assemblies depending on
server capabilities.
This commit is contained in:
Namhyeon, Go 2025-12-07 00:23:51 +09:00
parent 5b86a88111
commit 5747713f99

View File

@ -1,6 +1,6 @@
// AssemblyLoader.cs // AssemblyLoader.cs
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2025 Catswords OSS and WelsonJS Contributors // SPDX-FileCopyrightText: Namhyeon Go <gnh1201@catswords.re.kr>, 2025 Catswords OSS and WelsonJS Contributors
// https://github.com/gnh1201/welsonjs // https://github.com/gnh1201/welsonjs
// //
using System; using System;
@ -36,10 +36,23 @@ namespace WelsonJS.Launcher
private static bool _registered; private static bool _registered;
private static readonly string LoaderNamespace = typeof(AssemblyLoader).Namespace ?? "WelsonJS.Launcher"; private static readonly string LoaderNamespace = typeof(AssemblyLoader).Namespace ?? "WelsonJS.Launcher";
private static readonly HttpClient Http = new HttpClient private static readonly HttpClientHandler LegacyHttpHandler = new HttpClientHandler();
private static readonly HttpClientHandler HttpHandler = new HttpClientHandler
{ {
Timeout = TimeSpan.FromSeconds(300) // 5 minutes AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
}; };
private static readonly HttpClient LegacyHttp = CreateClient(LegacyHttpHandler); // No the Accept-Encoding (e.g., gzip, deflate) header
private static readonly HttpClient Http = CreateClient(HttpHandler); // With the Accept-Encoding (e.g., gzip, deflate) header
private static HttpClient CreateClient(HttpMessageHandler handler)
{
var client = new HttpClient(handler, disposeHandler: false)
{
Timeout = TimeSpan.FromSeconds(300) // 5 minutes
};
return client;
}
// -------------------- kernel32 native loading -------------------- // -------------------- kernel32 native loading --------------------
@ -327,9 +340,9 @@ namespace WelsonJS.Launcher
bool isDll = url.EndsWith(".dll", StringComparison.OrdinalIgnoreCase); // *.dll.gz bool isDll = url.EndsWith(".dll", StringComparison.OrdinalIgnoreCase); // *.dll.gz
bool downloaded = false; bool downloaded = false;
if (isDll && TryDownloadGzipToFile(gzUrl, dest)) if (isDll && TryDownloadCompressedFile(gzUrl, dest))
{ {
Logger.Info("Downloaded and decompressed gzip file to: {0}", dest); Logger.Info("Downloaded and decompressed file to: {0}", dest);
downloaded = true; downloaded = true;
} }
@ -365,13 +378,13 @@ namespace WelsonJS.Launcher
} }
private static bool TryDownloadGzipToFile(string gzUrl, string dest) private static bool TryDownloadCompressedFile(string gzUrl, string dest)
{ {
string tempFile = dest + ".tmp"; string tempFile = dest + ".tmp";
try try
{ {
using (var res = Http.GetAsync(gzUrl).GetAwaiter().GetResult()) using (var res = LegacyHttp.GetAsync(gzUrl).GetAwaiter().GetResult())
{ {
if (res.StatusCode == HttpStatusCode.NotFound) if (res.StatusCode == HttpStatusCode.NotFound)
return false; return false;