mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-05-07 12:16:04 +00:00
commit
46d0244c34
|
@ -5,6 +5,7 @@ using System.IO;
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -23,6 +24,7 @@ namespace WelsonJS.Launcher
|
|||
private List<IResourceTool> _tools = new List<IResourceTool>();
|
||||
private const int _blobTimeout = 5000;
|
||||
private readonly HttpClient _blobClient = new HttpClient();
|
||||
private readonly string _defaultMimeType = "application/octet-stream";
|
||||
|
||||
public ResourceServer(string prefix, string resourceName)
|
||||
{
|
||||
|
@ -128,8 +130,28 @@ namespace WelsonJS.Launcher
|
|||
|
||||
private async Task<bool> ServeBlob(HttpListenerContext context, string path)
|
||||
{
|
||||
byte[] data;
|
||||
string mimeType;
|
||||
|
||||
// Try serve data from the cached blob
|
||||
if (TryGetCachedBlob(path, out mimeType, true))
|
||||
{
|
||||
if (TryGetCachedBlob(path, out data))
|
||||
{
|
||||
if (String.IsNullOrEmpty(mimeType))
|
||||
{
|
||||
mimeType = _defaultMimeType;
|
||||
}
|
||||
|
||||
ServeResource(context, data, mimeType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If not cached yet
|
||||
try
|
||||
{
|
||||
|
||||
string blobServerPrefix = Program.GetAppConfig("BlobServerPrefix");
|
||||
string url = $"{blobServerPrefix}{path}";
|
||||
|
||||
|
@ -143,16 +165,106 @@ namespace WelsonJS.Launcher
|
|||
return false;
|
||||
}
|
||||
|
||||
byte[] data = await response.Content.ReadAsByteArrayAsync();
|
||||
string mimeType = response.Content.Headers.ContentType?.MediaType ?? "application/octet-stream";
|
||||
data = await response.Content.ReadAsByteArrayAsync();
|
||||
mimeType = response.Content.Headers.ContentType?.MediaType ?? _defaultMimeType;
|
||||
|
||||
ServeResource(context, data, mimeType);
|
||||
_ = TrySaveCachedBlob(path, data, mimeType);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.TraceError($"Failed to serve blob. Exception: {ex.ToString()}");
|
||||
Trace.TraceError($"Failed to serve blob. Exception: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCachedBlobPath(string path)
|
||||
{
|
||||
// Get a hash from the path
|
||||
string hashedPath;
|
||||
using (MD5 md5 = MD5.Create())
|
||||
{
|
||||
byte[] bHashedPath = md5.ComputeHash(Encoding.UTF8.GetBytes(path));
|
||||
hashedPath = BitConverter.ToString(bHashedPath).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
|
||||
// Get a sub-directory paths from the hashed path
|
||||
string[] subDirectoryPaths = new string[] {
|
||||
hashedPath.Substring(0, 2),
|
||||
hashedPath.Substring(2, 2),
|
||||
hashedPath.Substring(4, 2)
|
||||
};
|
||||
|
||||
// Return the cache path
|
||||
return Path.Combine(Program.GetAppDataPath(), "BlobCache", String.Join("\\", subDirectoryPaths), hashedPath);
|
||||
}
|
||||
|
||||
private bool TryGetCachedBlob(string path, out byte[] data, bool isMetadata = false)
|
||||
{
|
||||
string cachePath = GetCachedBlobPath(path);
|
||||
if (isMetadata)
|
||||
{
|
||||
cachePath = $"{cachePath}.meta";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(cachePath))
|
||||
{
|
||||
data = File.ReadAllBytes(cachePath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.TraceError($"Error: {ex.Message}");
|
||||
}
|
||||
|
||||
data = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryGetCachedBlob(string path, out string data, bool isMetadata = false)
|
||||
{
|
||||
byte[] bData;
|
||||
if (TryGetCachedBlob(path, out bData, isMetadata))
|
||||
{
|
||||
data = Encoding.UTF8.GetString(bData);
|
||||
return true;
|
||||
}
|
||||
|
||||
data = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> TrySaveCachedBlob(string path, byte[] data, string mimeType)
|
||||
{
|
||||
await Task.Delay(0);
|
||||
|
||||
try
|
||||
{
|
||||
string cachePath = GetCachedBlobPath(path);
|
||||
string cacheDirectory = Path.GetDirectoryName(cachePath);
|
||||
|
||||
// Is exists the cached blob directory
|
||||
if (!Directory.Exists(cacheDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(cacheDirectory);
|
||||
}
|
||||
|
||||
// Save the cache
|
||||
File.WriteAllBytes(cachePath, data);
|
||||
|
||||
// Save the cache meta
|
||||
File.WriteAllBytes($"{cachePath}.meta", Encoding.UTF8.GetBytes(mimeType));
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.TraceError($"Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
|
||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||
{
|
||||
await Task.Delay(0);
|
||||
|
||||
string word = path.Substring(Prefix.Length);
|
||||
|
||||
try
|
||||
|
@ -67,8 +69,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
{
|
||||
Server.ServeResource(context, $"<error>Failed to process completion request. {ex.Message}</error>", "application/xml", 500);
|
||||
}
|
||||
|
||||
await Task.Delay(0);
|
||||
}
|
||||
|
||||
private List<string> GetInstalledSoftwareExecutables()
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
|
||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||
{
|
||||
await Task.Delay(0);
|
||||
|
||||
string configName = path.Substring(Prefix.Length);
|
||||
|
||||
try
|
||||
|
@ -32,8 +34,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
{
|
||||
Server.ServeResource(context, $"<error>Failed to process Config request. {ex.Message}</error>", "application/xml", 500);
|
||||
}
|
||||
|
||||
await Task.Delay(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
|
||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||
{
|
||||
await Task.Delay(0);
|
||||
|
||||
string query = path.Substring(Prefix.Length);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(query) || query.Length > 255)
|
||||
|
@ -59,8 +61,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
{
|
||||
Server.ServeResource(context, $"<error>Failed to process DNS query. {ex.Message}</error>", "application/xml", 500);
|
||||
}
|
||||
|
||||
await Task.Delay(0);
|
||||
}
|
||||
|
||||
public List<string> QueryA(string domain) => QueryDns(domain, 1);
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
|
||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||
{
|
||||
await Task.Delay(0);
|
||||
|
||||
string endpoint = path.Substring(Prefix.Length);
|
||||
|
||||
if (endpoint.Equals("pubkey"))
|
||||
|
@ -34,8 +36,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
|||
}
|
||||
|
||||
Server.ServeResource(context);
|
||||
|
||||
await Task.Delay(0);
|
||||
}
|
||||
|
||||
public int GetOtp(string key)
|
||||
|
|
Loading…
Reference in New Issue
Block a user