/// <summary> /// Пытается получить из заголовков запроса TraceId и конвертировать в <see cref="Guid"/>?. /// </summary> /// <param name="context">HTTP контекст.</param> /// <param name="settings">Настройки TraceId.</param> /// <returns>TraceId.</returns> private static Guid?GetActualTraceId(HttpContext context, TraceIdSettings settings) { if (string.IsNullOrWhiteSpace(settings.Header)) { return(null); } Guid?traceId = null; if (context.Response.Headers.TryGetValue(settings.Header, out var traceIdString) && Guid.TryParse(traceIdString, out var traceGuid)) { traceId = traceGuid; } return(traceId); }
/// <summary> /// Мок HTTP контекста. /// </summary> /// <param name="traceIdSettings">Настройки TraceId.</param> /// <returns>Мок HTTP контекста.</returns> private static DefaultHttpContext GetMockedContextFor( TraceIdSettings traceIdSettings, out MockResponseFeature feature ) { feature = new MockResponseFeature(); var context = new DefaultHttpContext(); context.Features.Set <IHttpResponseFeature>(feature); if (!string.IsNullOrWhiteSpace(traceIdSettings.Header)) { context.Request.Headers.Add(traceIdSettings.Header, TraceContext.Current.TraceId?.ToString()); } if (!string.IsNullOrWhiteSpace(traceIdSettings.TraceIdSourceHeader)) { context.Request.Headers.Add(traceIdSettings.TraceIdSourceHeader, TraceContext.Current.TraceIdSource); } return(context); }
/// <summary> /// Конструктор по-умолчанию. /// </summary> /// <param name="next">Следующая Middleware в конвейере.</param> /// <param name="settings">Настройки TraceId.</param> public TraceIdMiddleware(RequestDelegate next, IOptions <TraceIdSettings> settings) { _next = next ?? throw new ArgumentNullException(nameof(next)); _settings = settings?.Value ?? throw new ArgumentNullException(nameof(settings)); }
/// <summary> /// Конструктор по-умолчанию. /// </summary> /// <param name="settings">Настройки сквозного идентификатора.</param> public TraceIdDelegatingHandler(IOptions <TraceIdSettings> settings) { _settings = settings.Value; }
public TraceIdMiddleware(RequestDelegate next, IOptions <TraceIdSettings> options, IAppContextAccessor contextAccessor) { _next = next ?? throw new ArgumentNullException(nameof(next)); _contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor)); _settings = options.Value; }
public async Task CorrectHandleSettingsAsync( int caseNumber, HttpStatusCode expectedStatusCode, string initialTraceString, bool generateIfNotPresent, bool throwBadRequestIfNotPresent, bool initialAndFinalTraceIdMustBeEqual ) { #region Arrange var initialTraceId = Guid.Parse(initialTraceString); var traceIdSettings = new TraceIdSettings { GenerateIfNotPresent = generateIfNotPresent, ThrowBadRequestIfNotPresent = throwBadRequestIfNotPresent }; var traceContext1 = TraceContext.Create(initialTraceId); var context = GetMockedContextFor(traceIdSettings, out var feature); var traceIdMiddleware = new TraceIdMiddleware(_ => feature.CompleteAsync(), Options.Create(traceIdSettings)); #endregion Arrange #region Act await traceIdMiddleware.Invoke(context, NullLogger <TraceIdMiddleware> .Instance); #endregion Act #region Assert var traceContext2 = TraceContext.Current; var actualTraceId = GetActualTraceId(context, traceIdSettings); Assert.Multiple(() => { Assert.AreEqual((int)expectedStatusCode, context.Response.StatusCode, "status code должен быть ожидаемым."); if (initialAndFinalTraceIdMustBeEqual) { Assert.AreEqual(initialTraceId, actualTraceId ?? Guid.Empty, "traceId до и после выполнения должны быть одинаковыми."); } if (traceIdSettings.GenerateIfNotPresent) { Assert.IsTrue(ReferenceEquals(traceContext1, traceContext2), "Инстансы должны быть одним и тем же."); Assert.AreNotEqual(Guid.Empty, TraceContext.Current.TraceId, "Если требуется генерировать при отсутствии TraceId, то TraceId не должен быть пустым."); if (actualTraceId.HasValue) { Assert.IsTrue(actualTraceId != Guid.Empty); } } else { if (initialTraceId == Guid.Empty) { Assert.IsNull(actualTraceId); } else { Assert.AreEqual(initialTraceId, actualTraceId); } } }); #endregion Assert }