protected virtual IItemsFeature CreateItems(IItemsFeature originalItems) { var result = new ItemsFeature(); foreach (var originalItem in originalItems.Items) { result.Items.Add(originalItem); } log.LogTrace($"Copied items: [{result.Items.Count}]"); return(result); }
public ModuleHttpContext(IFeatureCollection features, IServiceProvider requestServices, PathString pathBase) : base(new FeatureCollection(features)) { Features[typeof(IServiceProvidersFeature)] = new ServiceProvidersFeature() { RequestServices = requestServices }; var httpRequestFeature = Features.Get <IHttpRequestFeature>(); Features[typeof(IHttpRequestFeature)] = new HttpRequestFeature() { Body = httpRequestFeature.Body, Headers = httpRequestFeature.Headers, Method = httpRequestFeature.Method, Path = httpRequestFeature.Path, PathBase = new PathString(httpRequestFeature.PathBase).Add(pathBase), Protocol = httpRequestFeature.Protocol, QueryString = httpRequestFeature.QueryString, RawTarget = httpRequestFeature.RawTarget, Scheme = httpRequestFeature.Scheme }; Features[typeof(IItemsFeature)] = new ItemsFeature(); }
private static HttpContext CreateHttpContext(HttpContext originalContext) { // Clone the features so that a new set is used for each context. // The features themselves will be reused but not the collection. We // store the request container as a feature of the request and we don't want // the features added to one context/request to be visible on another. // // Note that just about everything in the HttpContext and HttpRequest is // backed by one of these features. So reusing the features means the HttContext // and HttpRequests are the same without needing to copy properties. To make them // different, we need to avoid copying certain features to that the objects don't // share the same storage/ IFeatureCollection features = new FeatureCollection(); string pathBase = ""; foreach (KeyValuePair <Type, object> kvp in originalContext.Features) { // Don't include the OData features. They may already // be present. This will get re-created later. // // Also, clear out the items feature, which is used // to store a few object, the one that is an issue here is the Url // helper, which has an affinity to the context. If we leave it, // the context of the helper no longer matches the new context and // the resulting url helper doesn't have access to the OData feature // because it's looking in the wrong context. // // Because we need a different request and response, leave those features // out as well. if (kvp.Key == typeof(IHttpRequestFeature)) { pathBase = ((IHttpRequestFeature)kvp.Value).PathBase; } if (kvp.Key == typeof(IODataBatchFeature) || kvp.Key == typeof(IODataFeature) || kvp.Key == typeof(IItemsFeature) || kvp.Key == typeof(IHttpRequestFeature) || kvp.Key == typeof(IHttpResponseFeature) || kvp.Key == typeof(IQueryFeature)) // Noted: we should not pass the QueryFeature from Main request to the sub request { continue; } if (kvp.Key == typeof(IEndpointFeature)) { continue; } features[kvp.Key] = kvp.Value; } // Add in an items, request and response feature. features[typeof(IItemsFeature)] = new ItemsFeature(); features[typeof(IHttpRequestFeature)] = new HttpRequestFeature { PathBase = pathBase }; features[typeof(IHttpResponseFeature)] = new HttpResponseFeature(); // Create a context from the factory or use the default context. HttpContext context = null; IHttpContextFactory httpContextFactory = originalContext.RequestServices.GetService <IHttpContextFactory>(); if (httpContextFactory != null) { context = httpContextFactory.Create(features); } else { context = new DefaultHttpContext(features); } // Clone parts of the request. All other parts of the request will be // populated during batch processing. context.Request.Cookies = originalContext.Request.Cookies; foreach (KeyValuePair <string, StringValues> header in originalContext.Request.Headers) { string headerKey = header.Key.ToLowerInvariant(); // do not copy over headers that should not be inherited from batch to individual requests if (!nonInheritableHeaders.Contains(headerKey)) { // some preferences may be inherited, others discarded if (headerKey == "prefer") { string preferencesToInherit = GetPreferencesToInheritFromBatch(header.Value); if (!string.IsNullOrEmpty(preferencesToInherit)) { context.Request.Headers.Add(header.Key, preferencesToInherit); } } // do not copy already existing headers, such as Cookie else if (!context.Request.Headers.ContainsKey(header.Key)) { context.Request.Headers.Add(header); } } } // Create a response body as the default response feature does not // have a valid stream. // Use a special batch stream that remains open after the writer is disposed. context.Response.Body = new ODataBatchStream(); return(context); }
private void Awake() { _itemsFeature = FindObjectOfType <ItemsFeature>(); }
/// <summary> /// Helper method to get the odata path for an arbitrary odata uri. /// </summary> /// <param name="request">The request instance in current context</param> /// <param name="uri">OData uri</param> /// <returns>The parsed odata path</returns> #if NETCORE public static ODataPath CreateODataPath(this HttpRequest request, Uri uri) { if (uri == null) { throw new ArgumentNullException("uri"); } // Clone the features so that a new set is used for each context. // The features themselves will be reused but not the collection. We // store the request container as a feature of the request and we don't want // the features added to one context/request to be visible on another. // // Note that just about everything in the HttpContext and HttpRequest is // backed by one of these features. So reusing the features means the HttContext // and HttpRequests are the same without needing to copy properties. To make them // different, we need to avoid copying certain features to that the objects don't // share the same storage/ IFeatureCollection features = new FeatureCollection(); foreach (KeyValuePair <Type, object> kvp in request.HttpContext.Features) { // Don't include the OData features. They may already // be present. This will get re-created later. // // Also, clear out the items feature, which is used // to store a few object, the one that is an issue here is the Url // helper, which has an affinity to the context. If we leave it, // the context of the helper no longer matches the new context and // the resulting url helper doesn't have access to the OData feature // because it's looking in the wrong context. // // Because we need a different request and response, leave those features // out as well. if (kvp.Key == typeof(IODataBatchFeature) || kvp.Key == typeof(IODataFeature) || kvp.Key == typeof(IItemsFeature) || kvp.Key == typeof(IHttpRequestFeature) || kvp.Key == typeof(IHttpResponseFeature)) { continue; } features[kvp.Key] = kvp.Value; } // Add in an items, request and response feature. features[typeof(IItemsFeature)] = new ItemsFeature(); features[typeof(IHttpRequestFeature)] = new HttpRequestFeature(); features[typeof(IHttpResponseFeature)] = new HttpResponseFeature(); // Create a context from the factory or use the default context. HttpContext context = new DefaultHttpContext(features); // Clone parts of the request. All other parts of the request will be // populated during batch processing. context.Request.Cookies = request.HttpContext.Request.Cookies; foreach (KeyValuePair <string, StringValues> header in request.HttpContext.Request.Headers) { context.Request.Headers.Add(header); } // Copy the Uri. context.Request.Scheme = uri.Scheme; context.Request.Host = uri.IsDefaultPort ? new HostString(uri.Host) : new HostString(uri.Host, uri.Port); context.Request.QueryString = new QueryString(uri.Query); context.Request.Path = new PathString(uri.AbsolutePath); // Get the existing OData route IRoutingFeature routingFeature = context.Features[typeof(IRoutingFeature)] as IRoutingFeature; ODataRoute route = routingFeature.RouteData.Routers.OfType <ODataRoute>().FirstOrDefault(); // Attempt to route the new request and extract the path. RouteContext routeContext = new RouteContext(context); route.RouteAsync(routeContext).Wait(); return(context.Request.ODataFeature().Path); }
private static HttpContext CreateHttpContext(HttpContext originalContext) { // Clone the features so that a new set is used for each context. // The features themselves will be reused but not the collection. We // store the request container as a feature of the request and we don't want // the features added to one context/request to be visible on another. // // Note that just about everything inm the HttpContext and HttpRequest is // backed by one of these features. So reusing the features means the HttContext // and HttpRequests are the same without needing to copy properties. To make them // different, we need to avoid copying certain features to that the objects don't // share the same storage/ IFeatureCollection features = new FeatureCollection(); string pathBase = ""; foreach (KeyValuePair <Type, object> kvp in originalContext.Features) { // Don't include the OData features. They may already // be present. This will get re-created later. // // Also, clear out the items feature, which is used // to store a few object, the one that is an issue here is the Url // helper, which has an affinity to the context. If we leave it, // the context of the helper no longer matches the new context and // the resulting url helper doesn't have access to the OData feature // because it's looking in the wrong context. // // Because we need a different request and response, leave those features // out as well. if (kvp.Key == typeof(IHttpRequestFeature)) { pathBase = ((IHttpRequestFeature)kvp.Value).PathBase; } if (kvp.Key == typeof(IODataBatchFeature) || kvp.Key == typeof(IODataFeature) || kvp.Key == typeof(IItemsFeature) || kvp.Key == typeof(IHttpRequestFeature) || kvp.Key == typeof(IHttpResponseFeature)) { continue; } features[kvp.Key] = kvp.Value; } // Add in an items, request and response feature. features[typeof(IItemsFeature)] = new ItemsFeature(); features[typeof(IHttpRequestFeature)] = new HttpRequestFeature { PathBase = pathBase }; features[typeof(IHttpResponseFeature)] = new HttpResponseFeature(); // Create a context from the factory or use the default context. HttpContext context = null; IHttpContextFactory httpContextFactory = originalContext.RequestServices.GetRequiredService <IHttpContextFactory>(); if (httpContextFactory != null) { context = httpContextFactory.Create(features); } else { context = new DefaultHttpContext(features); } // Clone parts of the request. All other parts of the request will be // populated during batch processing. context.Request.Cookies = originalContext.Request.Cookies; foreach (KeyValuePair <string, StringValues> header in originalContext.Request.Headers) { context.Request.Headers.Add(header); } // Create a response body as the default response feature does not // have a valid stream. context.Response.Body = new MemoryStream(); return(context); }