mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	Added request id functionality and general refactoring..also turned out i wasnt returning headers....sigh
This commit is contained in:
		@@ -20,6 +20,7 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
        private Dictionary<string, string> _routeClaimRequirement;
 | 
			
		||||
        private bool _isAuthorised;
 | 
			
		||||
        private List<ClaimToThing> _claimToQueries;
 | 
			
		||||
        private string _requestIdHeaderKey;
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder()
 | 
			
		||||
        {
 | 
			
		||||
@@ -96,6 +97,12 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithRequestIdKey(string input)
 | 
			
		||||
        {
 | 
			
		||||
            _requestIdHeaderKey = input;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithClaimsToHeaders(List<ClaimToThing> input)
 | 
			
		||||
        {
 | 
			
		||||
            _configHeaderExtractorProperties = input;
 | 
			
		||||
@@ -122,7 +129,7 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
 | 
			
		||||
        public ReRoute Build()
 | 
			
		||||
        {
 | 
			
		||||
            return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement, _isAuthorised, _claimToQueries);
 | 
			
		||||
            return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement, _isAuthorised, _claimToQueries, _requestIdHeaderKey);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -113,12 +113,17 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
 | 
			
		||||
                return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate,
 | 
			
		||||
                    reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated,
 | 
			
		||||
                    authOptionsForRoute, claimsToHeaders, claimsToClaims, reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries
 | 
			
		||||
                    authOptionsForRoute, claimsToHeaders, claimsToClaims, 
 | 
			
		||||
                    reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries,
 | 
			
		||||
                    reRoute.RequestIdKey
 | 
			
		||||
                    );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod,
 | 
			
		||||
                upstreamTemplate, isAuthenticated, null, new List<ClaimToThing>(), new List<ClaimToThing>(), reRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>());
 | 
			
		||||
            return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, 
 | 
			
		||||
                reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, 
 | 
			
		||||
                null, new List<ClaimToThing>(), new List<ClaimToThing>(), 
 | 
			
		||||
                reRoute.RouteClaimsRequirement, isAuthorised, new List<ClaimToThing>(),
 | 
			
		||||
                    reRoute.RequestIdKey);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private List<ClaimToThing> GetAddThingsToRequest(Dictionary<string,string> thingBeingAdded)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ namespace Ocelot.Configuration
 | 
			
		||||
{
 | 
			
		||||
    public class ReRoute
 | 
			
		||||
    {
 | 
			
		||||
        public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated, AuthenticationOptions authenticationOptions, List<ClaimToThing> configurationHeaderExtractorProperties, List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries)
 | 
			
		||||
        public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated, AuthenticationOptions authenticationOptions, List<ClaimToThing> configurationHeaderExtractorProperties, List<ClaimToThing> claimsToClaims, Dictionary<string, string> routeClaimsRequirement, bool isAuthorised, List<ClaimToThing> claimsToQueries, string requestIdKey)
 | 
			
		||||
        {
 | 
			
		||||
            DownstreamTemplate = downstreamTemplate;
 | 
			
		||||
            UpstreamTemplate = upstreamTemplate;
 | 
			
		||||
@@ -14,6 +14,7 @@ namespace Ocelot.Configuration
 | 
			
		||||
            AuthenticationOptions = authenticationOptions;
 | 
			
		||||
            RouteClaimsRequirement = routeClaimsRequirement;
 | 
			
		||||
            IsAuthorised = isAuthorised;
 | 
			
		||||
            RequestIdKey = requestIdKey;
 | 
			
		||||
            ClaimsToQueries = claimsToQueries
 | 
			
		||||
                ?? new List<ClaimToThing>();
 | 
			
		||||
            ClaimsToClaims = claimsToClaims 
 | 
			
		||||
@@ -33,6 +34,6 @@ namespace Ocelot.Configuration
 | 
			
		||||
        public List<ClaimToThing> ClaimsToHeaders { get; private set; }
 | 
			
		||||
        public List<ClaimToThing> ClaimsToClaims { get; private set; }
 | 
			
		||||
        public Dictionary<string, string> RouteClaimsRequirement { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public string RequestIdKey { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -19,6 +19,7 @@ namespace Ocelot.Configuration.Yaml
 | 
			
		||||
        public Dictionary<string, string> AddHeadersToRequest { get; set; }
 | 
			
		||||
        public Dictionary<string, string> AddClaimsToRequest { get; set; }
 | 
			
		||||
        public Dictionary<string, string> RouteClaimsRequirement { get; set; }
 | 
			
		||||
        public Dictionary<string, string> AddQueriesToRequest { get; set; } 
 | 
			
		||||
        public Dictionary<string, string> AddQueriesToRequest { get; set; }
 | 
			
		||||
        public string RequestIdKey { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Ocelot.Authentication.Handler.Creator;
 | 
			
		||||
@@ -16,6 +15,7 @@ using Ocelot.DownstreamRouteFinder.Finder;
 | 
			
		||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
 | 
			
		||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
 | 
			
		||||
using Ocelot.Headers;
 | 
			
		||||
using Ocelot.Infrastructure.Claims.Parser;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.QueryStrings;
 | 
			
		||||
using Ocelot.Request.Builder;
 | 
			
		||||
@@ -24,8 +24,6 @@ using Ocelot.Responder;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.DependencyInjection
 | 
			
		||||
{
 | 
			
		||||
    using Infrastructure.Claims.Parser;
 | 
			
		||||
 | 
			
		||||
    public static class ServiceCollectionExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static IServiceCollection AddOcelotYamlConfiguration(this IServiceCollection services, IConfigurationRoot configurationRoot)
 | 
			
		||||
@@ -48,6 +46,7 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            services.AddLogging();
 | 
			
		||||
 | 
			
		||||
            // ocelot services.
 | 
			
		||||
            services.AddSingleton<IRemoveHeaders, RemoveHeaders>();
 | 
			
		||||
            services.AddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>();
 | 
			
		||||
            services.AddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
 | 
			
		||||
            services.AddSingleton<IAuthoriser, ClaimsAuthoriser>();
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly RequestDelegate _next;
 | 
			
		||||
        private readonly IDownstreamRouteFinder _downstreamRouteFinder;
 | 
			
		||||
        private readonly IRequestScopedDataRepository _requestScopedDataRepository;
 | 
			
		||||
 | 
			
		||||
        public DownstreamRouteFinderMiddleware(RequestDelegate next, 
 | 
			
		||||
            IDownstreamRouteFinder downstreamRouteFinder, 
 | 
			
		||||
@@ -19,7 +18,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _downstreamRouteFinder = downstreamRouteFinder;
 | 
			
		||||
            _requestScopedDataRepository = requestScopedDataRepository;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(HttpContext context)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								src/Ocelot/Headers/IRemoveHeaders.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/Ocelot/Headers/IRemoveHeaders.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Headers
 | 
			
		||||
{
 | 
			
		||||
    public interface IRemoveHeaders
 | 
			
		||||
    {
 | 
			
		||||
        Response Remove(HttpResponseHeaders headers);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								src/Ocelot/Headers/RemoveHeaders.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/Ocelot/Headers/RemoveHeaders.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Headers
 | 
			
		||||
{
 | 
			
		||||
    public class RemoveHeaders : IRemoveHeaders
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Some webservers return headers that cannot be forwarded to the client
 | 
			
		||||
        /// in a given context such as transfer encoding chunked when ASP.NET is not
 | 
			
		||||
        /// returning the response in this manner
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private readonly List<string> _unsupportedHeaders = new List<string>
 | 
			
		||||
        {
 | 
			
		||||
            "Transfer-Encoding"
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public Response Remove(HttpResponseHeaders headers)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var unsupported in _unsupportedHeaders)
 | 
			
		||||
            {
 | 
			
		||||
                headers.Remove(unsupported);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new OkResponse();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,8 @@ namespace Ocelot.Middleware
 | 
			
		||||
        private readonly RequestDelegate _next;
 | 
			
		||||
        private readonly ILogger _logger;
 | 
			
		||||
 | 
			
		||||
        public ExceptionHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
 | 
			
		||||
        public ExceptionHandlerMiddleware(RequestDelegate next, 
 | 
			
		||||
            ILoggerFactory loggerFactory)
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
 | 
			
		||||
@@ -24,20 +25,25 @@ namespace Ocelot.Middleware
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                var message =
 | 
			
		||||
                    $"Exception caught in global error handler, exception message: {e.Message}, exception stack: {e.StackTrace}";
 | 
			
		||||
 | 
			
		||||
                if (e.InnerException != null)
 | 
			
		||||
                {
 | 
			
		||||
                    message = $"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}";
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var message = CreateMessage(context, e);
 | 
			
		||||
                _logger.LogError(new EventId(1, "Ocelot Global Error"), message, e);
 | 
			
		||||
 | 
			
		||||
                context.Response.StatusCode = 500;
 | 
			
		||||
                context.Response.ContentType = "application/json";
 | 
			
		||||
                await context.Response.WriteAsync("Internal Server Error");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static string CreateMessage(HttpContext context, Exception e)
 | 
			
		||||
        {
 | 
			
		||||
            var message =
 | 
			
		||||
                $"RequestId: {context.TraceIdentifier}, Exception caught in global error handler, exception message: {e.Message}, exception stack: {e.StackTrace}";
 | 
			
		||||
 | 
			
		||||
            if (e.InnerException != null)
 | 
			
		||||
            {
 | 
			
		||||
                message =
 | 
			
		||||
                    $"{message}, inner exception message {e.InnerException.Message}, inner exception stack {e.InnerException.StackTrace}";
 | 
			
		||||
            }
 | 
			
		||||
            return message;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ using Ocelot.Headers.Middleware;
 | 
			
		||||
using Ocelot.QueryStrings.Middleware;
 | 
			
		||||
using Ocelot.Request.Middleware;
 | 
			
		||||
using Ocelot.Requester.Middleware;
 | 
			
		||||
using Ocelot.RequestId.Middleware;
 | 
			
		||||
using Ocelot.Responder.Middleware;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Middleware
 | 
			
		||||
@@ -49,6 +50,9 @@ namespace Ocelot.Middleware
 | 
			
		||||
            // Then we get the downstream route information
 | 
			
		||||
            builder.UseDownstreamRouteFinderMiddleware();
 | 
			
		||||
 | 
			
		||||
            // Now we can look for the requestId
 | 
			
		||||
            builder.UseRequestIdMiddleware();
 | 
			
		||||
 | 
			
		||||
            // Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
 | 
			
		||||
            builder.UseIfNotNull(middlewareConfiguration.PreAuthenticationMiddleware);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,9 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Net.Http.Headers;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
@@ -10,8 +12,15 @@ namespace Ocelot.Request.Builder
 | 
			
		||||
{
 | 
			
		||||
    public class HttpRequestBuilder : IRequestBuilder
 | 
			
		||||
    {
 | 
			
		||||
        public async Task<Response<Request>> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers,
 | 
			
		||||
            IRequestCookieCollection cookies, Microsoft.AspNetCore.Http.QueryString queryString, string contentType)
 | 
			
		||||
        public async Task<Response<Request>> Build(
 | 
			
		||||
            string httpMethod, 
 | 
			
		||||
            string downstreamUrl, 
 | 
			
		||||
            Stream content, 
 | 
			
		||||
            IHeaderDictionary headers,
 | 
			
		||||
            IRequestCookieCollection cookies, 
 | 
			
		||||
            QueryString queryString, 
 | 
			
		||||
            string contentType, 
 | 
			
		||||
            RequestId.RequestId requestId)
 | 
			
		||||
        {
 | 
			
		||||
            var method = new HttpMethod(httpMethod);
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +30,7 @@ namespace Ocelot.Request.Builder
 | 
			
		||||
 | 
			
		||||
            if (content != null)
 | 
			
		||||
            {
 | 
			
		||||
                httpRequestMessage.Content = new ByteArrayContent(ToByteArray(content));
 | 
			
		||||
                httpRequestMessage.Content = new ByteArrayContent(await ToByteArray(content));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!string.IsNullOrEmpty(contentType))
 | 
			
		||||
@@ -45,6 +54,11 @@ namespace Ocelot.Request.Builder
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (RequestKeyIsNotNull(requestId) && !RequestIdInHeaders(requestId, httpRequestMessage.Headers))
 | 
			
		||||
            {
 | 
			
		||||
                ForwardRequestIdToDownstreamService(requestId, httpRequestMessage);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var cookieContainer = new CookieContainer();
 | 
			
		||||
 | 
			
		||||
            //todo get rid of if
 | 
			
		||||
@@ -59,13 +73,34 @@ namespace Ocelot.Request.Builder
 | 
			
		||||
            return new OkResponse<Request>(new Request(httpRequestMessage, cookieContainer));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private byte[] ToByteArray(Stream stream)
 | 
			
		||||
        private void ForwardRequestIdToDownstreamService(RequestId.RequestId requestId, HttpRequestMessage httpRequestMessage)
 | 
			
		||||
        {
 | 
			
		||||
            httpRequestMessage.Headers.Add(requestId.RequestIdKey, requestId.RequestIdValue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool RequestIdInHeaders(RequestId.RequestId requestId, HttpRequestHeaders headers)
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<string> value;
 | 
			
		||||
            if (headers.TryGetValues(requestId.RequestIdKey, out value))
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool RequestKeyIsNotNull(RequestId.RequestId requestId)
 | 
			
		||||
        {
 | 
			
		||||
            return !string.IsNullOrEmpty(requestId?.RequestIdKey) && !string.IsNullOrEmpty(requestId.RequestIdValue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task<byte[]> ToByteArray(Stream stream)
 | 
			
		||||
        {
 | 
			
		||||
            using (stream)
 | 
			
		||||
            {
 | 
			
		||||
                using (MemoryStream memStream = new MemoryStream())
 | 
			
		||||
                using (var memStream = new MemoryStream())
 | 
			
		||||
                {
 | 
			
		||||
                    stream.CopyTo(memStream);
 | 
			
		||||
                    await stream.CopyToAsync(memStream);
 | 
			
		||||
                    return memStream.ToArray();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,8 @@ namespace Ocelot.Request.Builder
 | 
			
		||||
            Stream content,
 | 
			
		||||
            IHeaderDictionary headers,
 | 
			
		||||
            IRequestCookieCollection cookies,
 | 
			
		||||
            Microsoft.AspNetCore.Http.QueryString queryString,
 | 
			
		||||
            string contentType);
 | 
			
		||||
            QueryString queryString,
 | 
			
		||||
            string contentType, 
 | 
			
		||||
            RequestId.RequestId requestId);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,17 +22,18 @@ namespace Ocelot.Request.Middleware
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
            var request = await _requestBuilder
 | 
			
		||||
              .Build(context.Request.Method, DownstreamUrl, context.Request.Body,
 | 
			
		||||
              context.Request.Headers, context.Request.Cookies, context.Request.QueryString, context.Request.ContentType);
 | 
			
		||||
            var buildResult = await _requestBuilder
 | 
			
		||||
                .Build(context.Request.Method, DownstreamUrl, context.Request.Body,
 | 
			
		||||
                    context.Request.Headers, context.Request.Cookies, context.Request.QueryString,
 | 
			
		||||
                    context.Request.ContentType, new RequestId.RequestId(DownstreamRoute?.ReRoute?.RequestIdKey, context.TraceIdentifier));
 | 
			
		||||
 | 
			
		||||
            if (request.IsError)
 | 
			
		||||
            if (buildResult.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                SetPipelineError(request.Errors);
 | 
			
		||||
                SetPipelineError(buildResult.Errors);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SetUpstreamRequestForThisRequest(request.Data);
 | 
			
		||||
            SetUpstreamRequestForThisRequest(buildResult.Data);
 | 
			
		||||
 | 
			
		||||
            await _next.Invoke(context);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								src/Ocelot/RequestId/DefaultRequestIdKey.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/Ocelot/RequestId/DefaultRequestIdKey.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
namespace Ocelot.RequestId
 | 
			
		||||
{
 | 
			
		||||
    public static class DefaultRequestIdKey
 | 
			
		||||
    {
 | 
			
		||||
        // This is set incase anyone isnt doing this specifically with there requests. 
 | 
			
		||||
        // It will not be forwarded on to downstream services unless specfied in the config.
 | 
			
		||||
        public const string Value = "RequestId";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/Ocelot/RequestId/Middleware/RequestIdMiddleware.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Primitives;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.RequestId.Middleware
 | 
			
		||||
{
 | 
			
		||||
    public class RequestIdMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly RequestDelegate _next;
 | 
			
		||||
 | 
			
		||||
        public RequestIdMiddleware(RequestDelegate next, 
 | 
			
		||||
            IRequestScopedDataRepository requestScopedDataRepository)
 | 
			
		||||
            :base(requestScopedDataRepository)
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
            SetTraceIdentifier(context);
 | 
			
		||||
 | 
			
		||||
            await _next.Invoke(context);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SetTraceIdentifier(HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
            var key = DefaultRequestIdKey.Value;
 | 
			
		||||
 | 
			
		||||
            if (DownstreamRoute.ReRoute.RequestIdKey != null)
 | 
			
		||||
            {
 | 
			
		||||
                key = DownstreamRoute.ReRoute.RequestIdKey;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            StringValues requestId;
 | 
			
		||||
 | 
			
		||||
            if (context.Request.Headers.TryGetValue(key, out requestId))
 | 
			
		||||
            {
 | 
			
		||||
                context.TraceIdentifier = requestId;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.RequestId.Middleware
 | 
			
		||||
{
 | 
			
		||||
    public static class RequestIdMiddlewareExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static IApplicationBuilder UseRequestIdMiddleware(this IApplicationBuilder builder)
 | 
			
		||||
        {
 | 
			
		||||
            return builder.UseMiddleware<RequestIdMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								src/Ocelot/RequestId/RequestId.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Ocelot/RequestId/RequestId.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
namespace Ocelot.RequestId
 | 
			
		||||
{
 | 
			
		||||
    public class RequestId
 | 
			
		||||
    {
 | 
			
		||||
        public RequestId(string requestIdKey, string requestIdValue)
 | 
			
		||||
        {
 | 
			
		||||
            RequestIdKey = requestIdKey;
 | 
			
		||||
            RequestIdValue = requestIdValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string RequestIdKey { get; private set; }
 | 
			
		||||
        public string RequestIdValue { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Logging;
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.Middleware;
 | 
			
		||||
using Ocelot.Responder;
 | 
			
		||||
@@ -25,7 +27,6 @@ namespace Ocelot.Requester.Middleware
 | 
			
		||||
 | 
			
		||||
        public async Task Invoke(HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            var response = await _requester.GetResponse(Request);
 | 
			
		||||
 | 
			
		||||
            if (response.IsError)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,10 @@
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.Extensions.Primitives;
 | 
			
		||||
using Ocelot.Headers;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Responder
 | 
			
		||||
@@ -11,15 +15,42 @@ namespace Ocelot.Responder
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class HttpContextResponder : IHttpResponder
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IRemoveHeaders _removeHeaders;
 | 
			
		||||
 | 
			
		||||
        public HttpContextResponder(IRemoveHeaders removeHeaders)
 | 
			
		||||
        {
 | 
			
		||||
            _removeHeaders = removeHeaders;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<Response> SetResponseOnHttpContext(HttpContext context, HttpResponseMessage response)
 | 
			
		||||
        {
 | 
			
		||||
            context.Response.OnStarting(x =>
 | 
			
		||||
            _removeHeaders.Remove(response.Headers);
 | 
			
		||||
 | 
			
		||||
            foreach (var httpResponseHeader in response.Headers)
 | 
			
		||||
            {
 | 
			
		||||
                context.Response.StatusCode = (int)response.StatusCode;
 | 
			
		||||
                context.Response.Headers.Add(httpResponseHeader.Key, new StringValues(httpResponseHeader.Value.ToArray()));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var content = await response.Content.ReadAsStreamAsync();
 | 
			
		||||
 | 
			
		||||
            context.Response.Headers.Add("Content-Length", new[] { content.Length.ToString() });
 | 
			
		||||
 | 
			
		||||
            context.Response.OnStarting(state =>
 | 
			
		||||
            {
 | 
			
		||||
                var httpContext = (HttpContext)state;
 | 
			
		||||
 | 
			
		||||
                httpContext.Response.StatusCode = (int)response.StatusCode;
 | 
			
		||||
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
            }, context);
 | 
			
		||||
 | 
			
		||||
            await context.Response.WriteAsync(await response.Content.ReadAsStringAsync());
 | 
			
		||||
            using (var reader = new StreamReader(content))
 | 
			
		||||
            {
 | 
			
		||||
                var responseContent = reader.ReadToEnd();
 | 
			
		||||
                await context.Response.WriteAsync(responseContent);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new OkResponse();       
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user