Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(logging): middleware loggings changed to compile-time logging + deprecated cleanup and minor imp #85

Merged
merged 9 commits into from
Jul 24, 2024
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@

[_vNext_](https://github.com/sketch7/FluentlyHttpClient/compare/3.8.1...3.9.0) (2020-X-X)

## [4.0.0](https://github.com/sketch7/FluentlyHttpClient/compare/3.9.6...4.0.0) (2024-07-23)
## [4.0.0](https://github.com/sketch7/FluentlyHttpClient/compare/3.9.6...4.0.0) (2024-07-24)

### Features
- **http client builder:** configurable http version/policy via `WithVersion`, `WithVersionPolicy`
- **http client builder:** defaults to http version http2.0

### Performance
- **logging:** middleware loggings changed to compile-time logging
- **request builder:** uri interpolation regex compile-time

### BREAKING CHANGES

- **deps:** now target .net8
- **http request:** remove deprecated `FluentHttpRequest.Formatters`
- **models:** change several options/context models to `record`'s

## [3.9.6](https://github.com/sketch7/FluentlyHttpClient/compare/3.9.5...3.9.6) (2024-06-11)

Expand Down
10 changes: 5 additions & 5 deletions src/FluentlyHttpClient/Caching/HttpResponseSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class HttpResponseSerializer : IHttpResponseSerializer
Hash = response.GetRequestHash(),
ReasonPhrase = response.ReasonPhrase,
StatusCode = (int)response.StatusCode,
Url = response.Message.RequestMessage.RequestUri.ToString(),
Url = response.Message.RequestMessage!.RequestUri!.ToString(),
Version = response.Message.Version.ToString(),
Headers = new(response.Headers),
RequestMessage = response.Message.RequestMessage
Expand All @@ -43,18 +43,18 @@ public class HttpResponseSerializer : IHttpResponseSerializer
/// <returns></returns>
public Task<FluentHttpResponse> Deserialize(IHttpResponseStore item)
{
var contentType = new ContentType(item.ContentHeaders.ContentType);
var contentType = new ContentType(item.ContentHeaders!.ContentType!);
var encoding = string.IsNullOrEmpty(contentType.CharSet) ? Encoding.UTF8 : Encoding.GetEncoding(contentType.CharSet);

var cloned = new FluentHttpResponse(new((HttpStatusCode)item.StatusCode)
{
Content = new StringContent(item.Content, encoding, contentType.MediaType),
Content = new StringContent(item.Content!, encoding, contentType.MediaType),
ReasonPhrase = item.ReasonPhrase,
Version = new(item.Version),
Version = new(item.Version!),
RequestMessage = item.RequestMessage,
}); // todo: add items?

cloned.Headers.AddRange(item.Headers);
cloned.Headers.AddRange(item.Headers!);

return Task.FromResult(cloned);
}
Expand Down
8 changes: 4 additions & 4 deletions src/FluentlyHttpClient/FluentHttpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public interface IFluentHttpClient : IDisposable
/// <summary>
/// Gets the default formatter to be used when serializing body content. e.g. JSON, XML, etc...
/// </summary>
MediaTypeFormatter DefaultFormatter { get; }
MediaTypeFormatter? DefaultFormatter { get; }

/// <summary>Get the formatter for an HTTP content type.</summary>
/// <param name="contentType">The HTTP content type (or <c>null</c> to automatically select one).</param>
Expand Down Expand Up @@ -102,7 +102,7 @@ public class FluentHttpClient : IFluentHttpClient
public MediaTypeFormatterCollection Formatters { get; }

/// <inheritdoc />
public MediaTypeFormatter DefaultFormatter { get; }
public MediaTypeFormatter? DefaultFormatter { get; }

/// <inheritdoc />
public HttpRequestHeaders Headers { get; }
Expand Down Expand Up @@ -175,7 +175,7 @@ public FluentHttpRequestBuilder CreateRequest(string? uriTemplate = null, object
/// <inheritdoc />
public async Task<FluentHttpResponse> Send(FluentHttpRequest request)
{
if (request == null) throw new ArgumentNullException(nameof(request));
ArgumentNullException.ThrowIfNull(request, nameof(request));

var requestId = request.Message.AddRequestId();

Expand All @@ -193,7 +193,7 @@ public async Task<FluentHttpResponse> Send(FluentHttpRequest request)

public async Task<FluentHttpResponse> Send(HttpRequestMessage request)
{
if (request == null) throw new ArgumentNullException(nameof(request));
ArgumentNullException.ThrowIfNull(request, nameof(request));

var requestId = request.AddRequestId();
await RawHttpClient.SendAsync(request);
Expand Down
12 changes: 3 additions & 9 deletions src/FluentlyHttpClient/FluentHttpClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ public class FluentHttpClientBuilder : IFluentHttpHeaderBuilder<FluentHttpClient
/// <summary>
/// Gets the identifier specified.
/// </summary>
public string? Identifier { get; private set; }
public string Identifier { get; private set; } = null!;

private readonly IServiceProvider _serviceProvider;
private readonly IFluentHttpClientFactory _fluentHttpClientFactory;
private readonly FluentHttpMiddlewareBuilder _middlewareBuilder;
private string? _baseUrl;
private TimeSpan _timeout;
private readonly FluentHttpHeaders _headers = new();
private readonly FluentHttpHeaders _headers = [];
private Action<FluentHttpRequestBuilder>? _requestBuilderDefaults;
private HttpMessageHandler? _httpMessageHandler;
private readonly FormatterOptions _formatterOptions = new();
Expand Down Expand Up @@ -73,42 +73,36 @@ public FluentHttpClientBuilder WithTimeout(TimeSpan timeout)
return this;
}

/// <inheritdoc />
public FluentHttpClientBuilder WithHeader(string key, string value)
{
_headers.Set(key, value);
return this;
}

/// <inheritdoc />
public FluentHttpClientBuilder WithHeader(string key, StringValues values)
{
_headers.Set(key, values);
return this;
}

/// <inheritdoc />
public FluentHttpClientBuilder WithHeaders(IDictionary<string, string> headers)
{
_headers.SetRange(headers);
return this;
}

/// <inheritdoc />
public FluentHttpClientBuilder WithHeaders(IDictionary<string, string[]> headers)
{
_headers.SetRange(headers);
return this;
}

/// <inheritdoc />
public FluentHttpClientBuilder WithHeaders(IDictionary<string, StringValues> headers)
{
_headers.SetRange(headers);
return this;
}

/// <inheritdoc />
public FluentHttpClientBuilder WithHeaders(FluentHttpHeaders headers)
{
_headers.SetRange(headers);
Expand Down Expand Up @@ -287,7 +281,7 @@ internal class MediaTypeFormatterComparer : IEqualityComparer<MediaTypeFormatter
{
public static readonly MediaTypeFormatterComparer Instance = new();

public bool Equals(MediaTypeFormatter x, MediaTypeFormatter y) => x?.GetType() == y?.GetType();
public bool Equals(MediaTypeFormatter? x, MediaTypeFormatter? y) => x?.GetType() == y?.GetType();

public int GetHashCode(MediaTypeFormatter obj) => obj.GetType().GetHashCode();
}
10 changes: 5 additions & 5 deletions src/FluentlyHttpClient/FluentHttpClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ public class FluentHttpClientOptions
/// <summary>
/// Gets or sets the identifier (key) for the HTTP client.
/// </summary>
public string? Identifier { get; set; }
public string Identifier { get; set; } = null!;

/// <summary>
/// Gets or sets the headers which should be sent with each request.
/// </summary>
public FluentHttpHeaders? Headers { get; set; }
public FluentHttpHeaders Headers { get; set; } = null!;

/// <summary>
/// Gets or sets the middleware builder.
/// </summary>
public FluentHttpMiddlewareBuilder MiddlewareBuilder { get; set; }
public FluentHttpMiddlewareBuilder MiddlewareBuilder { get; set; } = null!;

/// <summary>
/// Gets or sets handler to customize request on creation. In order to specify defaults as desired, or so.
Expand All @@ -51,7 +51,7 @@ public class FluentHttpClientOptions
/// <summary>
/// Gets or sets formatters to be used for content negotiation, for "Accept" and body media formats. e.g. JSON, XML, etc...
/// </summary>
public MediaTypeFormatterCollection? Formatters { get; set; }
public MediaTypeFormatterCollection Formatters { get; set; } = null!;

/// <summary>
/// Gets or sets the default formatter to be used for content negotiation body format. e.g. JSON, XML, etc...
Expand All @@ -75,7 +75,7 @@ public FormatterOptions()
/// <summary>
/// Configure formatters to be used.
/// </summary>
public MediaTypeFormatterCollection Formatters { get; } = new();
public MediaTypeFormatterCollection Formatters { get; } = [];

/// <summary>
/// Set default formatter to be used when serializing body content and the preferred "Accept".
Expand Down
37 changes: 19 additions & 18 deletions src/FluentlyHttpClient/FluentHttpHeaders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace FluentlyHttpClient;
/// <summary>
/// <see cref="FluentHttpHeaders"/> options.
/// </summary>
public class FluentHttpHeadersOptions
public record FluentHttpHeadersOptions
{
/// <summary>
/// Predicate function to exclude headers from being hashed in <see cref="FluentHttpHeaders.ToHashString"/>.
Expand Down Expand Up @@ -43,9 +43,9 @@ public partial class FluentHttpHeaders : IFluentHttpHeaderBuilder<FluentHttpHead
{
private static readonly FluentHttpHeadersOptions DefaultOptions = new();
private FluentHttpHeadersOptions _options = DefaultOptions;
private readonly Dictionary<string, string[]> _data = new(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, string[]?> _data = new(StringComparer.OrdinalIgnoreCase);

public string[] this[string key]
public string[]? this[string key]
{
get => _data[key];
set => _data[key] = value;
Expand Down Expand Up @@ -122,7 +122,7 @@ public FluentHttpHeaders(HttpHeaders headers)
/// <param name="value">Header value to add.</param>
public FluentHttpHeaders Add(string header, string value)
{
_data.Add(header, new[] { value });
_data.Add(header, [value]);
return this;
}

Expand Down Expand Up @@ -189,7 +189,7 @@ public FluentHttpHeaders AddRange(IDictionary<string, IEnumerable<string>> heade
public FluentHttpHeaders AddRange(IDictionary<string, string> headers)
{
foreach (var header in headers)
_data.Add(header.Key, new[] { header.Value });
_data.Add(header.Key, [header.Value]);
return this;
}

Expand Down Expand Up @@ -240,7 +240,7 @@ public StringValues Get(string header)
/// <param name="value">Header value to add.</param>
public FluentHttpHeaders Set(string header, string value)
{
this[header] = new[] { value };
this[header] = [value];
return this;
}

Expand Down Expand Up @@ -374,11 +374,12 @@ public string ToHashString()
/// <summary>
/// Converts to dictionary.
/// </summary>
public Dictionary<string, string[]> ToDictionary() => _data;
public Dictionary<string, string[]?> ToDictionary() => _data;

FluentHttpHeaders IFluentHttpHeaderBuilder<FluentHttpHeaders>.WithHeader(string key, string value) => Add(key, value);
FluentHttpHeaders IFluentHttpHeaderBuilder<FluentHttpHeaders>.WithHeader(string key, StringValues values) => Add(key, values);
FluentHttpHeaders IFluentHttpHeaderBuilder<FluentHttpHeaders>.WithHeaders(IDictionary<string, string> headers) => SetRange(headers);
FluentHttpHeaders IFluentHttpHeaderBuilder<FluentHttpHeaders>.WithHeaders(IDictionary<string, string[]> headers) => SetRange(headers);
FluentHttpHeaders IFluentHttpHeaderBuilder<FluentHttpHeaders>.WithHeaders(IDictionary<string, StringValues> headers) => SetRange(headers);
FluentHttpHeaders IFluentHttpHeaderBuilder<FluentHttpHeaders>.WithHeaders(FluentHttpHeaders headers) => SetRange(headers);
}
Expand Down Expand Up @@ -407,43 +408,43 @@ public StringValues AcceptLanguage
/// <summary>
/// Gets or sets the Authorization header.
/// </summary>
public string Authorization
public string? Authorization
{
get => Get(HeaderTypes.Authorization);
set => this[HeaderTypes.Authorization] = new[] { value };
set => this[HeaderTypes.Authorization] = [value];
}

/// <summary>
/// Gets or sets the Cache-Control header.
/// </summary>
public string CacheControl
public string? CacheControl
{
get => Get(HeaderTypes.CacheControl);
set => this[HeaderTypes.CacheControl] = new[] { value };
set => this[HeaderTypes.CacheControl] = [value];
}

/// <summary>
/// Gets or sets the Content-Type header.
/// </summary>
public string ContentType
public string? ContentType
{
get => Get(HeaderTypes.ContentType);
set => this[HeaderTypes.ContentType] = new[] { value };
set => this[HeaderTypes.ContentType] = [value];
}

/// <summary>
/// Gets or sets the User-Agent header.
/// </summary>
public string UserAgent
public string? UserAgent
{
get => Get(HeaderTypes.UserAgent);
set => this[HeaderTypes.UserAgent] = new[] { value };
set => this[HeaderTypes.UserAgent] = [value];
}

/// <summary>
/// Gets or sets the X-Forwarded-For header.
/// </summary>
public StringValues XForwardedFor
public StringValues? XForwardedFor
{
get => Get(HeaderTypes.XForwardedFor);
set => this[HeaderTypes.XForwardedFor] = value;
Expand All @@ -452,9 +453,9 @@ public StringValues XForwardedFor
/// <summary>
/// Gets or sets the X-Forwarded-Host header.
/// </summary>
public string XForwardedHost
public string? XForwardedHost
{
get => Get(HeaderTypes.XForwardedHost);
set => this[HeaderTypes.XForwardedHost] = new[] { value };
set => this[HeaderTypes.XForwardedHost] = [value];
}
}
6 changes: 3 additions & 3 deletions src/FluentlyHttpClient/FluentHttpMessageExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Text;
using System.Text;

namespace FluentlyHttpClient;

Expand All @@ -14,12 +14,12 @@ public static class FluentHttpMessageExtensions
public static async Task<FluentHttpResponse> Clone(this FluentHttpResponse response)
{
var contentString = await response.Content.ReadAsStringAsync();
var contentType = response.Content.Headers.ContentType;
var contentType = response.Content.Headers.ContentType!;
var encoding = string.IsNullOrEmpty(contentType.CharSet) ? Encoding.UTF8 : Encoding.GetEncoding(contentType.CharSet);

var cloned = new FluentHttpResponse(new(response.StatusCode)
{
Content = new StringContent(contentString, encoding, contentType.MediaType),
Content = new StringContent(contentString, encoding, contentType.MediaType!),
ReasonPhrase = response.ReasonPhrase,
Version = response.Message.Version,
RequestMessage = response.Message.RequestMessage,
Expand Down
12 changes: 3 additions & 9 deletions src/FluentlyHttpClient/FluentHttpRequest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace FluentlyHttpClient;
namespace FluentlyHttpClient;

/// <summary>
/// Fluent HTTP request, which wraps the <see cref="HttpRequestMessage"/> and add additional features.
Expand Down Expand Up @@ -30,7 +30,7 @@ public HttpMethod Method
/// <summary>
/// Gets or sets the <see cref="System.Uri"/> for the HTTP request.
/// </summary>
public Uri Uri
public Uri? Uri
{
get => Message.RequestUri;
set => Message.RequestUri = value;
Expand All @@ -42,7 +42,7 @@ public Uri Uri
public HttpRequestHeaders Headers => Message.Headers;

/// <summary>
/// Determine whether has success status otherwise it will throw or not.
/// Determine whether it has success status otherwise it will throw or not.
/// </summary>
public bool HasSuccessStatusOrThrow { get; set; }

Expand All @@ -54,12 +54,6 @@ public Uri Uri
/// <inheritdoc />
public IDictionary<object, object> Items { get; protected set; }

/// <summary>
/// Formatters to be used for content negotiation for "Accept" and also sending formats. e.g. (JSON, XML)
/// </summary>
[Obsolete("This was added to be passed down to the middleware. Instead in middleware use FluentHttpMiddlewareClientContext.Formatters.")]
public MediaTypeFormatterCollection? Formatters { get; set; } // deprecated: remove

/// <summary>
/// Initializes a new instance.
/// </summary>
Expand Down
Loading
Loading