147 lines
5.5 KiB
C#
147 lines
5.5 KiB
C#
using DigitalData.Core.Abstractions.Client;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Net;
|
|
using System.Web;
|
|
|
|
namespace DigitalData.Core.Client
|
|
{
|
|
public class BaseHttpClientService : IBaseHttpClientService
|
|
{
|
|
protected readonly HttpClient _client;
|
|
protected readonly CookieContainer _cookies;
|
|
|
|
[StringSyntax("Uri")]
|
|
protected readonly string _uri;
|
|
|
|
protected readonly string _path;
|
|
|
|
protected IEnumerable<KeyValuePair<string, object>>? _headers;
|
|
|
|
protected IEnumerable<KeyValuePair<string, object?>>? _queryParams;
|
|
|
|
internal BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IHttpClientOptions clientOptions)
|
|
{
|
|
_client = client;
|
|
_cookies = cookieContainer;
|
|
_uri = clientOptions.Uri.Trim(URI_TRIM_CHARS);
|
|
_path = clientOptions.Path?.Trim(URI_TRIM_CHARS) ?? string.Empty;
|
|
_headers = clientOptions.Headers;
|
|
_queryParams = clientOptions.QueryParams;
|
|
}
|
|
|
|
public CookieCollection GetCookies(string path = "") => _cookies.GetCookies(uri: new Uri(UriCombine(_uri, path, path.Trim(URI_TRIM_CHARS))));
|
|
|
|
public async Task<HttpResponseMessage> FetchAsync(
|
|
string? scheme = null,
|
|
int? port = null,
|
|
string path = "",
|
|
IEnumerable<KeyValuePair<string, object?>>? queryParams = null,
|
|
HttpMethod? method = null,
|
|
HttpContent? body = null,
|
|
IEnumerable<KeyValuePair<string, object>>? form = null,
|
|
IEnumerable<KeyValuePair<string, object>>? headers = null,
|
|
bool sendWithCookie = true,
|
|
bool saveCookie = true
|
|
)
|
|
{
|
|
// merge with default headers
|
|
if(_headers is not null)
|
|
{
|
|
if (headers is null)
|
|
headers = _headers;
|
|
else
|
|
{
|
|
var mergedHeaders = headers.ToList();
|
|
mergedHeaders.AddRange(_headers);
|
|
headers = mergedHeaders;
|
|
}
|
|
}
|
|
|
|
// Add default query parameters
|
|
if(_queryParams is not null)
|
|
{
|
|
if (queryParams is null)
|
|
queryParams = _queryParams;
|
|
else
|
|
{
|
|
var mergedQueryParams = queryParams.ToList();
|
|
mergedQueryParams.AddRange(_queryParams);
|
|
queryParams = mergedQueryParams;
|
|
}
|
|
}
|
|
|
|
// set default HTTP method as GET
|
|
method ??= HttpMethod.Get;
|
|
|
|
// create URL
|
|
var uriBuilder = new UriBuilder(_uri);
|
|
if (scheme is not null)
|
|
uriBuilder.Scheme = scheme;
|
|
if (port is int portInt)
|
|
uriBuilder.Port = portInt;
|
|
uriBuilder.Path = UriCombine(_path, path?.Trim(URI_TRIM_CHARS) ?? string.Empty);
|
|
|
|
// Add query parameters if provided
|
|
if (queryParams?.Any() ?? false)
|
|
{
|
|
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
|
|
|
var flagParams = queryParams.Where(param => param.Value is null).Select(param => param.Key);
|
|
|
|
var valueParams = queryParams.Where(param => param.Value is not null);
|
|
|
|
foreach (var param in valueParams)
|
|
query[param.Key] = param.Value switch
|
|
{
|
|
bool b => b.ToString().ToLower(),
|
|
_ => param.Value.ToString()
|
|
};
|
|
|
|
if (flagParams.Any())
|
|
uriBuilder.Query = string.Join(QUERY_SEPARATOR, query.ToString(), string.Join(QUERY_SEPARATOR, flagParams));
|
|
else uriBuilder.Query = query.ToString();
|
|
}
|
|
|
|
var requestUri = uriBuilder.Uri;
|
|
|
|
var requestMessage = new HttpRequestMessage(method, requestUri);
|
|
|
|
// Add headers if provided
|
|
headers?.ForEach(header => requestMessage.Headers.Add(header.Key, header.Value.ToString()));
|
|
|
|
// Add cookie to request
|
|
if (sendWithCookie)
|
|
{
|
|
var cookieHeader = _cookies.GetCookieHeader(requestUri);
|
|
if (!string.IsNullOrWhiteSpace(cookieHeader))
|
|
{
|
|
requestMessage.Headers.Add("Cookie", cookieHeader);
|
|
}
|
|
}
|
|
|
|
// Add body content if provided
|
|
if (body != null && form != null)
|
|
throw new InvalidOperationException("Body content and form data cannot both be set.");
|
|
else if (body != null)
|
|
requestMessage.Content = body;
|
|
else if (form != null)
|
|
requestMessage.Content = new FormUrlEncodedContent(form.Select(e => KeyValuePair.Create(e.Key, e.Value.ToString())));
|
|
|
|
var response = await _client.SendAsync(requestMessage);
|
|
|
|
// Add response cookies to cookies
|
|
if (saveCookie)
|
|
if (response.Headers.TryGetValues("Set-Cookie", out var cookies))
|
|
foreach (var cookie in cookies)
|
|
_cookies.SetCookies(requestUri, cookie);
|
|
|
|
return response;
|
|
}
|
|
|
|
internal static readonly char[] URI_TRIM_CHARS = { '\\', '/', ' ' };
|
|
|
|
internal static string UriCombine(params string[] paths) => System.IO.Path.Combine(paths).Replace("\\", "/");
|
|
|
|
internal static readonly char QUERY_SEPARATOR = '&';
|
|
}
|
|
} |