예제 #1
0
        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();
        }
예제 #3
0
        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);
        }
예제 #4
0
 private void Awake()
 {
     _itemsFeature = FindObjectOfType <ItemsFeature>();
 }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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);
        }