using System.Net.Http.Headers; using RobotNet10.Script.IO; namespace RobotNet10.ScriptEngine.IO; /// /// Implementation of HTTP connection using HttpClient. /// public class HttpConnection : IHttpConnection { private readonly HttpClient _httpClient; private bool _disposed; public string BaseUrl { get; } public bool IsConnected { get; private set; } public HttpConnection(string baseUrl, TimeSpan? timeout = null) { BaseUrl = baseUrl.TrimEnd('/'); _httpClient = new HttpClient { BaseAddress = new Uri(BaseUrl), Timeout = timeout ?? TimeSpan.FromSeconds(30) }; IsConnected = false; } public async Task ConnectAsync() { // HTTP doesn't require explicit connection, but we can verify connectivity try { var response = await _httpClient.GetAsync("/"); IsConnected = true; } catch { IsConnected = false; throw; } } public Task DisconnectAsync() { IsConnected = false; return Task.CompletedTask; } public async Task GetAsync(string path, Dictionary? headers = null) { EnsureConnected(); using var request = new HttpRequestMessage(HttpMethod.Get, path); AddHeaders(request, headers); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } public async Task PostAsync(string path, string content, string contentType = "application/json", Dictionary? headers = null) { EnsureConnected(); using var request = new HttpRequestMessage(HttpMethod.Post, path); request.Content = new StringContent(content); request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); AddHeaders(request, headers); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } public async Task PutAsync(string path, string content, string contentType = "application/json", Dictionary? headers = null) { EnsureConnected(); using var request = new HttpRequestMessage(HttpMethod.Put, path); request.Content = new StringContent(content); request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); AddHeaders(request, headers); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } public async Task DeleteAsync(string path, Dictionary? headers = null) { EnsureConnected(); using var request = new HttpRequestMessage(HttpMethod.Delete, path); AddHeaders(request, headers); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } private static void AddHeaders(HttpRequestMessage request, Dictionary? headers) { if (headers != null) { foreach (var header in headers) { request.Headers.Add(header.Key, header.Value); } } } private void EnsureConnected() { if (!IsConnected) { throw new InvalidOperationException("HTTP connection is not connected. Call ConnectAsync() first."); } } public void Dispose() { if (!_disposed) { _httpClient?.Dispose(); IsConnected = false; _disposed = true; } GC.SuppressFinalize(this); } }