diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ChromiumDevTools.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ChromiumDevTools.cs index d30201a..ecd3e25 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ChromiumDevTools.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ChromiumDevTools.cs @@ -11,7 +11,7 @@ using System.Net.Http; using System.Security; using System.Threading.Tasks; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class ChromiumDevTools : IApiEndpoint { @@ -29,9 +29,9 @@ namespace WelsonJS.Launcher.ResourceTools _logger = logger; } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Completion.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Completion.cs index 5934ebc..291db13 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Completion.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Completion.cs @@ -16,7 +16,7 @@ using System.Net.Http; using System.Collections.Concurrent; using log4net; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class Completion : IApiEndpoint { @@ -38,9 +38,9 @@ namespace WelsonJS.Launcher.ResourceTools Task.Run(async () => await SafeDiscoverAsync(DiscoverFromProgramDirectories)); } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/DnsQuery.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/DnsQuery.cs index 31ee547..4035c49 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/DnsQuery.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/DnsQuery.cs @@ -13,7 +13,7 @@ using System.Net.Sockets; using System.Text; using System.Threading.Tasks; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class DnsQuery : IApiEndpoint { @@ -36,9 +36,9 @@ namespace WelsonJS.Launcher.ResourceTools DnsServer = Program.GetAppConfig("DnsServerAddress"); } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ImageColorPicker.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ImageColorPicker.cs index da801a5..a75ef85 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ImageColorPicker.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/ImageColorPicker.cs @@ -14,7 +14,7 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { /// /// POST image-color-picker/ with a unified JSON body: @@ -45,9 +45,9 @@ namespace WelsonJS.Launcher.ResourceTools _logger = logger; } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/IpQuery.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/IpQuery.cs index 94d0776..bc338dd 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/IpQuery.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/IpQuery.cs @@ -25,7 +25,7 @@ using System.Threading.Tasks; using System.Web; using System.Xml.Linq; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class IpQuery : IApiEndpoint { @@ -42,9 +42,9 @@ namespace WelsonJS.Launcher.ResourceTools _logger = logger; } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) { diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Settings.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Settings.cs index c61487a..73409cc 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Settings.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Settings.cs @@ -15,7 +15,7 @@ using System.Resources; using System.Threading.Tasks; using System.Xml.Linq; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class Settings : IApiEndpoint { @@ -32,9 +32,9 @@ namespace WelsonJS.Launcher.ResourceTools _logger = logger; } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.Equals(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.Equals(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/TwoFactorAuth.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/TwoFactorAuth.cs index 3acd9f9..555ccdb 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/TwoFactorAuth.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/TwoFactorAuth.cs @@ -14,7 +14,7 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class TwoFactorAuth : IApiEndpoint { @@ -33,9 +33,9 @@ namespace WelsonJS.Launcher.ResourceTools _logger = logger; } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Whois.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Whois.cs index dcf0e6f..06c1259 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Whois.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ApiEndpoints/Whois.cs @@ -10,7 +10,7 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; -namespace WelsonJS.Launcher.ResourceTools +namespace WelsonJS.Launcher.ApiEndpoints { public class Whois : IApiEndpoint { @@ -27,9 +27,9 @@ namespace WelsonJS.Launcher.ResourceTools _logger = logger; } - public bool CanHandle(string path) + public bool CanHandle(HttpListenerContext context, string path) { - return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); + return path != null && path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase); } public async Task HandleAsync(HttpListenerContext context, string path) diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/IApiEndpoint.cs b/WelsonJS.Augmented/WelsonJS.Launcher/IApiEndpoint.cs index 6633774..ff00dce 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/IApiEndpoint.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/IApiEndpoint.cs @@ -1,4 +1,4 @@ -// IResourceTool.cs +// IApiEndpoint.cs // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2025 Catswords OSS and WelsonJS Contributors // https://github.com/gnh1201/welsonjs @@ -9,22 +9,56 @@ using System.Threading.Tasks; namespace WelsonJS.Launcher { /// - /// Defines a contract for resource tools that can handle specific HTTP requests. + /// Defines a contract for API endpoints that can selectively handle incoming HTTP requests. /// public interface IApiEndpoint { /// - /// Determines whether this tool can handle the specified path. + /// Determines whether this endpoint is able to handle the given HTTP request. /// - /// The request path to check. - /// True if this tool can handle the request; otherwise, false. - bool CanHandle(string path); + /// + /// This method is invoked by the request dispatcher to decide which endpoint + /// should process the incoming request. + /// + /// Implementations may use the provided for fast + /// routing decisions, while the full can be + /// inspected for HTTP method, headers, query parameters, authentication + /// state, or other request-specific information. + /// + /// This method should be free of side effects and must not write to the response. + /// + /// + /// The HTTP listener context containing the incoming request details. + /// + /// + /// The normalized request path extracted from the request URL + /// (e.g. "/api/status"). + /// + /// + /// true if this endpoint is responsible for handling the request; + /// otherwise, false. + /// + bool CanHandle(HttpListenerContext context, string path); + /// - /// Asynchronously processes the HTTP request for the specified path. + /// Asynchronously handles the HTTP request assigned to this endpoint. /// - /// The HTTP listener context containing request and response objects. - /// The request path to handle. - /// A task representing the asynchronous operation. + /// + /// This method is called only after has returned + /// true for the same request. + /// + /// Implementations are responsible for writing the response and properly + /// terminating the request lifecycle. + /// + /// + /// The HTTP listener context containing request and response objects. + /// + /// + /// The request path associated with this endpoint. + /// + /// + /// A task that represents the asynchronous handling operation. + /// Task HandleAsync(HttpListenerContext context, string path); } } \ No newline at end of file diff --git a/WelsonJS.Augmented/WelsonJS.Launcher/ResourceServer.cs b/WelsonJS.Augmented/WelsonJS.Launcher/ResourceServer.cs index f5055c5..2a83aef 100644 --- a/WelsonJS.Augmented/WelsonJS.Launcher/ResourceServer.cs +++ b/WelsonJS.Augmented/WelsonJS.Launcher/ResourceServer.cs @@ -31,7 +31,7 @@ namespace WelsonJS.Launcher private bool _isRunning; private string _prefix; private string _resourceName; - private List _tools = new List(); + private readonly List _apis = new List(); private BlobConfig _blobConfig; private readonly ILog _logger; @@ -66,15 +66,15 @@ namespace WelsonJS.Launcher _logger?.Error($"FetchBlobConfig failed: {t.Exception}"); }, TaskScheduler.Default); - // Add resource tools - _tools.Add(new ResourceTools.Completion(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.Settings(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.ChromiumDevTools(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.DnsQuery(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.IpQuery(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.TwoFactorAuth(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.Whois(this, _httpClient, _logger)); - _tools.Add(new ResourceTools.ImageColorPicker(this, _httpClient, _logger)); + // Add API endpoints + _apis.Add(new ApiEndpoints.Completion(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.Settings(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.ChromiumDevTools(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.DnsQuery(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.IpQuery(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.TwoFactorAuth(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.Whois(this, _httpClient, _logger)); + _apis.Add(new ApiEndpoints.ImageColorPicker(this, _httpClient, _logger)); // Register the prefix _listener.Prefixes.Add(prefix); @@ -151,12 +151,12 @@ namespace WelsonJS.Launcher return; } - // Serve from a resource tool - foreach (var tool in _tools) + // Serve via API endpoints + foreach (var api in _apis) { - if (tool.CanHandle(path)) + if (api.CanHandle(context, path)) { - await tool.HandleAsync(context, path); + await api.HandleAsync(context, path); return; } }