using System.Diagnostics; using System.Text; using System.Text.Json; namespace S8n.Components.Basics; public class HttpRequest { private static readonly HttpClient _httpClient = new(); private static string EnsureUrlSchema(string url) { if (string.IsNullOrWhiteSpace(url)) return url; // Check if the URL already has a scheme if (Uri.TryCreate(url, UriKind.Absolute, out var uri) && !string.IsNullOrEmpty(uri.Scheme)) { return url; // Already has a scheme } // If no scheme, prepend http:// // Check if it starts with // (protocol-relative URL) if (url.StartsWith("//")) { return "http:" + url; } // Otherwise prepend http:// return "http://" + url; } public object Execute(string method, string url, Dictionary? headers = null, object? body = null) { if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentException("URL is required"); } if (string.IsNullOrWhiteSpace(method)) { throw new ArgumentException("HTTP method is required"); } var normalizedUrl = EnsureUrlSchema(url); var stopwatch = Stopwatch.StartNew(); try { using var request = new HttpRequestMessage(HttpMethod.Parse(method), normalizedUrl); // Add headers if provided if (headers != null) { foreach (var header in headers) { request.Headers.TryAddWithoutValidation(header.Key, header.Value); } } // Add body if provided and method supports it if (body != null && (method.Equals("POST", StringComparison.OrdinalIgnoreCase) || method.Equals("PUT", StringComparison.OrdinalIgnoreCase) || method.Equals("PATCH", StringComparison.OrdinalIgnoreCase))) { string jsonBody; if (body is JsonElement jsonElement) { jsonBody = jsonElement.GetRawText(); } else { jsonBody = JsonSerializer.Serialize(body); } request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); } // Execute request using var response = _httpClient.SendAsync(request).GetAwaiter().GetResult(); stopwatch.Stop(); // Read response content var responseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); // Extract response headers var responseHeaders = new Dictionary(); foreach (var header in response.Headers) { responseHeaders[header.Key] = string.Join(", ", header.Value); } foreach (var header in response.Content.Headers) { responseHeaders[header.Key] = string.Join(", ", header.Value); } return new { StatusCode = (int)response.StatusCode, StatusText = response.StatusCode.ToString(), Response = responseContent, Headers = responseHeaders, Duration = stopwatch.ElapsedMilliseconds }; } catch (HttpRequestException ex) { stopwatch.Stop(); throw new Exception($"HTTP request failed: {ex.Message}"); } catch (UriFormatException ex) { throw new Exception($"Invalid URL format: {ex.Message}"); } catch (Exception ex) when (ex is not ArgumentException) { stopwatch.Stop(); throw new Exception($"Request failed: {ex.Message}"); } } }