public void OnNext_RequestObserver_With_Null_Action_Value_And_Null_Controller_Value() { // Arrange var observer = new AspNetCoreDiagnosticListenerObserver(); var registry = new DefaultCollectorRegistry(); var factory = Metrics.WithCustomRegistry(registry); var listener = new DiagnosticListener("TestListener2"); listener.Subscribe(observer); var context = new DefaultHttpContext(); context.Request.Method = "GET"; context.Request.Path = new PathString("/api/test2"); context.Response.StatusCode = 200; var httpConnectionFeature = new HttpConnectionFeature { ConnectionId = "12345" }; context.Features.Set <IHttpConnectionFeature>(httpConnectionFeature); var routeData = new RouteData(); routeData.Values.Add("controller", null); routeData.Values.Add("action", null); // Act var activity = new Activity("Microsoft.AspNetCore.Hosting.HttpRequestIn"); listener.StartActivity(activity, new { HttpContext = context }); listener.Write("Microsoft.AspNetCore.Mvc.AfterAction", new { httpContext = context, routeData }); listener.StopActivity(activity, new { HttpContext = context }); // Assert var requestCounter = (Counter)observer.GetType().GetField("_requestCounter", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(observer); var requestSummary = (Summary)observer.GetType().GetField("_requestSummary", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(observer); var counterMetrics = requestCounter.Collect(); var summaryMetrics = requestSummary.Collect(); Assert.IsTrue(counterMetrics.First().metric.Any(p => p.label[1].value == "/api/test2")); Assert.IsNotNull(summaryMetrics.First().metric[0].summary); }
public void OnNext_RequestObserved_RequestStopEventReceived() { // Arrange var observer = new AspNetCoreDiagnosticListenerObserver(); var listener = new DiagnosticListener("TestListener"); listener.Subscribe(observer); var context = new DefaultHttpContext(); context.Request.Method = "GET"; context.Request.Path = new PathString("/api/test"); context.Response.StatusCode = 200; var httpConnectionFeature = new HttpConnectionFeature { ConnectionId = "1234" }; context.Features.Set <IHttpConnectionFeature>(httpConnectionFeature); var routeData = new RouteData(); routeData.Values.Add("controller", "test"); routeData.Values.Add("action", "get"); // Act // Create the activity, start it and immediately stop it. This will // cause the OnNext method in the observer to be called with the events // Microsoft.AspNetCore.Hosting.HttpRequestIn.Start and // Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop. In addition, // Activity.Current will be managed by the listener. var activity = new Activity("Microsoft.AspNetCore.Hosting.HttpRequestIn"); listener.StartActivity(activity, new { HttpContext = context }); listener.Write("Microsoft.AspNetCore.Mvc.AfterAction", new { httpContext = context, routeData }); listener.StopActivity(activity, new { HttpContext = context }); // Assert var requestCounter = (Counter)observer.GetType().GetField("_requestCounter", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(observer); var requestSummary = (Summary)observer.GetType().GetField("_requestSummary", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(observer); var counterMetrics = requestCounter.Collect(); var summaryMetrics = requestSummary.Collect(); Assert.AreEqual(1, counterMetrics.First().metric.Count); Assert.AreEqual(1, counterMetrics.First().metric[0].counter.value); Assert.AreEqual(1, summaryMetrics.First().metric.Count); Assert.IsNotNull(summaryMetrics.First().metric[0].summary); }
public static (HttpContext context, HttpConnectionFeature feature) CreateHttpContext() { HttpConnectionFeature feature = new HttpConnectionFeature(); FeatureCollection features = new FeatureCollection(); features.Set <IHttpConnectionFeature>(feature); Mock <HttpContext> contextMock = new Mock <HttpContext>(); contextMock.SetupGet(c => c.Features).Returns(features); return(contextMock.Object, feature); }
private static HttpClient GetByConfig(Action <WebHostBuilder> configureDelegate) { var b = new WebHostBuilder(); configureDelegate(b); b.UseStartup <TSetup>(); var fc = new FeatureCollection(); var f = new HttpConnectionFeature(); f.RemoteIpAddress = new IPAddress(new byte[] { 172, 0, 0, 1 }); f.RemotePort = 80; fc.Set(f); var srv = new Microsoft.AspNetCore.TestHost.TestServer(b, fc); return(srv.CreateClient()); }
public void InitializeSetsIpFromRemoteIpAddress() { var requestTelemetry = new RequestTelemetry(); var contextAccessor = HttpContextAccessorHelper.CreateHttpContextAccessor(requestTelemetry); var httpConnectionFeature = new HttpConnectionFeature { RemoteIpAddress = new IPAddress(new byte[] { 1, 2, 3, 4 }) }; contextAccessor.HttpContext.Features.Set <IHttpConnectionFeature>(httpConnectionFeature); var initializer = new ClientIpHeaderTelemetryInitializer(contextAccessor); initializer.Initialize(requestTelemetry); Assert.Equal("1.2.3.4", requestTelemetry.Context.Location.Ip); }
private static void CloneHttpContext(HttpContext context, HttpConnectionContext connection) { // The reason we're copying the base features instead of the HttpContext properties is // so that we can get all of the logic built into DefaultHttpContext to extract higher level // structure from the low level properties var existingRequestFeature = context.Features.Get <IHttpRequestFeature>() !; var requestFeature = new HttpRequestFeature(); requestFeature.Protocol = existingRequestFeature.Protocol; requestFeature.Method = existingRequestFeature.Method; requestFeature.Scheme = existingRequestFeature.Scheme; requestFeature.Path = existingRequestFeature.Path; requestFeature.PathBase = existingRequestFeature.PathBase; requestFeature.QueryString = existingRequestFeature.QueryString; requestFeature.RawTarget = existingRequestFeature.RawTarget; var requestHeaders = new Dictionary <string, StringValues>(existingRequestFeature.Headers.Count, StringComparer.OrdinalIgnoreCase); foreach (var header in existingRequestFeature.Headers) { requestHeaders[header.Key] = header.Value; } requestFeature.Headers = new HeaderDictionary(requestHeaders); var existingConnectionFeature = context.Features.Get <IHttpConnectionFeature>(); var connectionFeature = new HttpConnectionFeature(); if (existingConnectionFeature != null) { connectionFeature.ConnectionId = existingConnectionFeature.ConnectionId; connectionFeature.LocalIpAddress = existingConnectionFeature.LocalIpAddress; connectionFeature.LocalPort = existingConnectionFeature.LocalPort; connectionFeature.RemoteIpAddress = existingConnectionFeature.RemoteIpAddress; connectionFeature.RemotePort = existingConnectionFeature.RemotePort; } // The response is a dud, you can't do anything with it anyways var responseFeature = new HttpResponseFeature(); var features = new FeatureCollection(); features.Set <IHttpRequestFeature>(requestFeature); features.Set <IHttpResponseFeature>(responseFeature); features.Set <IHttpResponseBodyFeature>(new StreamResponseBodyFeature(Stream.Null)); features.Set <IHttpConnectionFeature>(connectionFeature); // REVIEW: We could strategically look at adding other features but it might be better // if we expose a callback that would allow the user to preserve HttpContext properties. var newHttpContext = new DefaultHttpContext(features); newHttpContext.TraceIdentifier = context.TraceIdentifier; var endpointFeature = context.Features.Get <IEndpointFeature>(); newHttpContext.SetEndpoint(endpointFeature?.Endpoint); CloneUser(newHttpContext, context); connection.ServiceScope = context.RequestServices.CreateAsyncScope(); newHttpContext.RequestServices = connection.ServiceScope.Value.ServiceProvider; // REVIEW: This extends the lifetime of anything that got put into HttpContext.Items newHttpContext.Items = new Dictionary <object, object?>(context.Items); connection.HttpContext = newHttpContext; }
private static HttpContext CloneHttpContext(HttpContext context) { // The reason we're copying the base features instead of the HttpContext properties is // so that we can get all of the logic built into DefaultHttpContext to extract higher level // structure from the low level properties var existingRequestFeature = context.Features.Get <IHttpRequestFeature>(); var requestFeature = new HttpRequestFeature(); requestFeature.Protocol = existingRequestFeature.Protocol; requestFeature.Method = existingRequestFeature.Method; requestFeature.Scheme = existingRequestFeature.Scheme; requestFeature.Path = existingRequestFeature.Path; requestFeature.PathBase = existingRequestFeature.PathBase; requestFeature.QueryString = existingRequestFeature.QueryString; requestFeature.RawTarget = existingRequestFeature.RawTarget; var requestHeaders = new Dictionary <string, StringValues>(existingRequestFeature.Headers.Count, StringComparer.Ordinal); foreach (var header in existingRequestFeature.Headers) { requestHeaders[header.Key] = header.Value; } requestFeature.Headers = new HeaderDictionary(requestHeaders); var existingConnectionFeature = context.Features.Get <IHttpConnectionFeature>(); var connectionFeature = new HttpConnectionFeature(); if (existingConnectionFeature != null) { connectionFeature.ConnectionId = existingConnectionFeature.ConnectionId; connectionFeature.LocalIpAddress = existingConnectionFeature.LocalIpAddress; connectionFeature.LocalPort = existingConnectionFeature.LocalPort; connectionFeature.RemoteIpAddress = existingConnectionFeature.RemoteIpAddress; connectionFeature.RemotePort = existingConnectionFeature.RemotePort; } // The response is a dud, you can't do anything with it anyways var responseFeature = new HttpResponseFeature(); var features = new FeatureCollection(); features.Set <IHttpRequestFeature>(requestFeature); features.Set <IHttpResponseFeature>(responseFeature); features.Set <IHttpConnectionFeature>(connectionFeature); // REVIEW: We could strategically look at adding other features but it might be better // if we expose a callback that would allow the user to preserve HttpContext properties. var newHttpContext = new DefaultHttpContext(features); newHttpContext.TraceIdentifier = context.TraceIdentifier; CloneUser(newHttpContext, context); // Making request services function property could be tricky and expensive as it would require // DI scope per connection. It would also mean that services resolved in middleware leading up to here // wouldn't be the same instance (but maybe that's fine). For now, we just return an empty service provider newHttpContext.RequestServices = EmptyServiceProvider.Instance; // REVIEW: This extends the lifetime of anything that got put into HttpContext.Items newHttpContext.Items = new Dictionary <object, object>(context.Items); return(newHttpContext); }