Confluence init

This commit is contained in:
2026-04-13 13:40:32 +03:00
parent c8b7395ba8
commit 87fb9e8df8
13 changed files with 1092 additions and 34 deletions

View File

@@ -0,0 +1,154 @@
using System.Net.Http;
using System.Text.Json;
namespace LazyBear.Confluence;
public static class ConfluenceClientFactory
{
public static HttpClient CreateClient(string baseUrl, HttpClientHandler? handler = null)
{
handler ??= new HttpClientHandler();
return new HttpClient(handler)
{
BaseAddress = new Uri(baseUrl.TrimEnd('/')),
DefaultRequestHeaders =
{
HttpHeaders
{
["User-Agent"] = "LazyBear-Confluence-MCP/1.0",
["Accept"] = "application/json"
}
}
};
}
public static ConfluenceHttpClientProvider CreateProvider(string baseUrl, string? token = null, HttpClientHandler? handler = null)
{
var httpHandler = handler ?? new HttpClientHandler();
var httpClient = CreateClient(baseUrl, httpHandler);
return new ConfluenceHttpClientProvider(httpClient, baseUrl, token);
}
}
public sealed class ConfluenceHttpClientProvider
{
public HttpClient Client { get; }
public string BaseUrl => HttpBaseAddress?.Root ?? string.Empty;
public string? AccessToken { get; }
public string? InitializationError { get; }
private Uri? HttpBaseAddress;
public ConfluenceHttpClientProvider(HttpClient client, string baseUrl, string? token = null)
{
Client = client;
HttpBaseAddress = new Uri(baseUrl.TrimEnd('/'));
AccessToken = token;
}
public ConcurrentDictionary<string, JsonElement> Cache { get; } = new();
public async Task<T?> GetJsonAsync<T>(HttpRequestMessage request) where T : class
{
using var response = await Client.SendAsync(request).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return default;
}
var errorBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new HttpRequestException($"[{request.RequestMethod}] {request.RequestUri}: {response.StatusCode} {errorBody}");
}
return await JsonSerializer.DeserializeAsync<T>(response.Content, request, JsonDefaults.DefaultSerializerOptions)
.ConfigureAwait(false);
}
public async Task<JsonElement?> GetJsonAsync(HttpRequestMessage request)
{
if (Cache.TryGetValue(request.RequestUri!.ToString(), out var cached))
{
return cached;
}
using var response = await Client.SendAsync(request).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
}
var errorBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new HttpRequestException($"[{request.RequestMethod}] {request.RequestUri}: {response.StatusCode} {errorBody}");
}
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var element = JsonDocument.Parse(json).RootElement;
Cache[request.RequestUri!.ToString()] = element;
return element;
}
public HttpRequestMessage CreateGetRequest(string resource)
{
return new HttpRequestMessage(HttpMethod.Get, HttpBaseAddress + resource);
}
public HttpRequestMessage CreatePostRequest(string resource, object? body = null)
{
var request = new HttpRequestMessage(HttpMethod.Post, HttpBaseAddress + resource);
request.Content = new StringContent(JsonSerializer.Serialize(body), System.Text.Encoding.UTF8, "application/json");
return request;
}
public HttpRequestMessage CreatePutRequest(string resource, object? body = null)
{
var request = new HttpRequestMessage(HttpMethod.Put, HttpBaseAddress + resource);
request.Content = new StringContent(JsonSerializer.Serialize(body), System.Text.Encoding.UTF8, "application/json");
return request;
}
public HttpRequestMessage CreateDeleteRequest(string resource)
{
return new HttpRequestMessage(HttpMethod.Delete, HttpBaseAddress + resource);
}
public void SetAccessToken(string token)
{
AccessToken = token;
}
public void SetRequestHeaders(HttpHeaders headers)
{
var cloned = Client.DefaultRequestHeaders.Clone();
foreach (var header in headers)
{
cloned.Add(header.Key, header.Value);
}
Client.DefaultRequestHeaders = cloned;
}
public void AddRequestHeader(string name, params string[] values)
{
foreach (var value in values)
{
Client.DefaultRequestHeaders.Add(name, value);
}
}
private class JsonDefaults
{
public static readonly JsonSerializerOptions DefaultSerializerOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new JsonStringEnumConverter() }
};
}
}