Skip to content

Commit

Permalink
Merge pull request #63 from atidev/app_http_context_more_safe_in_non_…
Browse files Browse the repository at this point in the history
…http_context

Add nullable annotation for AppHttpContext.cs & it can work without http context
  • Loading branch information
AlexFate committed Mar 5, 2024
2 parents 0e1ed49 + 44055ef commit b132482
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 72 deletions.
135 changes: 65 additions & 70 deletions ATI.Services.Common/Variables/AppHttpContext.cs
Original file line number Diff line number Diff line change
@@ -1,99 +1,94 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using ATI.Services.Common.Extensions;
using ATI.Services.Common.Metrics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;

namespace ATI.Services.Common.Variables
namespace ATI.Services.Common.Variables;

internal static class AppHttpContext
{
internal static class AppHttpContext
{
private static IServiceProvider _services;
private static IServiceProvider? _services;

/// <summary>
/// Provides static access to the framework's services provider
/// </summary>
public static IServiceProvider Services
/// <summary>
/// Provides static access to the framework's services provider
/// </summary>
public static IServiceProvider? Services
{
get => _services;
set
{
get => _services;
set
{
if (_services != null)
{
return;
}
// If _services already initialized -> return
if (_services is not null)
return;

_services = value;
}
_services = value;
}
}

public static string[] MetricsHeadersValues => GetHeadersValues(MetricsLabelsAndHeaders.UserHeaders);
public static Dictionary<string, string> HeadersAndValuesToProxy(List<string> headersToProxy) => GetHeadersAndValues(headersToProxy);
public static string[] MetricsHeadersValues => GetHeadersValues(MetricsLabelsAndHeaders.UserHeaders);
public static Dictionary<string, string> HeadersAndValuesToProxy(IReadOnlyCollection<string>? headersToProxy) => GetHeadersAndValues(headersToProxy);

/// <summary>
/// Provides static access to the current HttpContext
/// </summary>
private static HttpContext Current
/// <summary>
/// Provides static access to the current HttpContext
/// </summary>
private static HttpContext? Ctx
{
get
{
get
{
var httpContextAccessor =
_services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
return httpContextAccessor?.HttpContext;
}
ArgumentNullException.ThrowIfNull(Services, "IServiceProvider can't be null. Try do services.AddServiceVariables() in app configuration");

var httpContextAccessor = Services.GetService<IHttpContextAccessor>();
return httpContextAccessor?.HttpContext;
}
}

private static string[] GetHeadersValues(string[] headersNames)
private static string[] GetHeadersValues(IReadOnlyCollection<string>? headersNames)
{
try
{
if (headersNames == null || headersNames.Length == 0)
return headersNames;
if (headersNames is null || headersNames.Count == 0)
return Array.Empty<string>();

var context = Current;
var headersValues = headersNames.Select(label => GetHeaderValue(context, label)).ToArray();
var headersValues = headersNames.Select(label => GetHeaderValue(Ctx, label)).ToArray();
return headersValues;
}

private static string GetHeaderValue(HttpContext context, string headerName)
catch (ObjectDisposedException) // when thing happen outside http ctx e.g eventbus event handler
{
if (context == null)
{
return "This service";
}
return Array.Empty<string>();
}
}

if (context.Request.Headers.TryGetValue(headerName, out var headerValues))
{
if (!headerValues[0].IsNullOrEmpty())
{
return headerValues[0];
}
}
private static string GetHeaderValue(HttpContext? context, string headerName)
{
if (context is null)
return "This service";

return "Empty";
}
if (context.Request.Headers.TryGetValue(headerName, out var headerValues) && !StringValues.IsNullOrEmpty(headerValues))
return headerValues[0];

Check warning on line 71 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 71 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 71 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / release

Possible null reference return.

Check warning on line 71 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / release

Possible null reference return.

private static Dictionary<string, string> GetHeadersAndValues(IReadOnlyCollection<string> headersNames)
{
if (headersNames == null || headersNames.Count == 0)
return null;
return "Empty";
}

var context = Current;
if (context == null)
return null;
private static Dictionary<string, string> GetHeadersAndValues(IReadOnlyCollection<string>? headersNames)
{
if (headersNames is null || headersNames.Count == 0 || Ctx is null)
return new Dictionary<string, string>();

return headersNames
.Select(header => context.Request.Headers.TryGetValue(header, out var headerValues)
&& !StringValues.IsNullOrEmpty(headerValues)
? new
{
Header = header,
Value = headerValues[0]
}
: null)
.Where(headerAndValue => headerAndValue != null)
.ToDictionary(headerAndValue => headerAndValue.Header,
headerAndValue => headerAndValue.Value);
}
return headersNames

Check warning on line 81 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of reference types in value of type 'Dictionary<string, string?>' doesn't match target type 'Dictionary<string, string>'.

Check warning on line 81 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of reference types in value of type 'Dictionary<string, string?>' doesn't match target type 'Dictionary<string, string>'.

Check warning on line 81 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / release

Nullability of reference types in value of type 'Dictionary<string, string?>' doesn't match target type 'Dictionary<string, string>'.

Check warning on line 81 in ATI.Services.Common/Variables/AppHttpContext.cs

View workflow job for this annotation

GitHub Actions / release

Nullability of reference types in value of type 'Dictionary<string, string?>' doesn't match target type 'Dictionary<string, string>'.
.Select(header => Ctx.Request.Headers.TryGetValue(header, out var headerValues)
&& !StringValues.IsNullOrEmpty(headerValues)
? new
{
Header = header,
Value = headerValues[0]
}
: null)
.Where(headerAndValue => headerAndValue != null)
.ToDictionary(headerAndValue => headerAndValue!.Header,
headerAndValue => headerAndValue!.Value);
}
}
4 changes: 2 additions & 2 deletions ATI.Services.Common/Variables/ServiceVariablesExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ public static void AddServiceVariables(this IServiceCollection services)
{
services.ConfigureByName<ServiceVariablesOptions>();
services.AddTransient<ServiceVariablesInitializer>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

services.AddHttpContextAccessor();
AppHttpContext.Services = services.BuildServiceProvider(new ServiceProviderOptions().ValidateOnBuild);
}
}
Expand Down

0 comments on commit b132482

Please sign in to comment.