Optimisation of Reverse Proxy RRS feed

  • Question

  • Hi guys,

    So I am currently working on implementing a new project I am using MVC .NET Core 3.1 to do all of my developments.

    I have a requirement to create a reverse proxy which all of my client side applications will connect to. The one I am having the biggest issue with is a connection to an on premise Analysis Services Instance, because the response content can get quite large it results in slow response times for my client.

    Here is the code that I have:

    using Microsoft.AspNetCore.Http;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    namespace SSASProxyTest2
        public class ReverseProxyMiddleware
            private static readonly HttpClient _httpClient = new HttpClient();
            private readonly RequestDelegate _nextMiddleware;
            public ReverseProxyMiddleware(RequestDelegate nextMiddleware)
                _nextMiddleware = nextMiddleware;
            public async Task Invoke(HttpContext context)
                var targetUri = BuildTargetUri(context.Request);
                if (targetUri != null)
                    var targetRequestMessage = CreateTargetMessage(context, targetUri);
                    using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
                        context.Response.StatusCode = (int)responseMessage.StatusCode;
                        CopyFromTargetResponseHeaders(context, responseMessage);
                        await responseMessage.Content.CopyToAsync(context.Response.Body);
                await _nextMiddleware(context);
            private HttpRequestMessage CreateTargetMessage(HttpContext context, Uri targetUri)
                var requestMessage = new HttpRequestMessage();
                CopyFromOriginalRequestContentAndHeaders(context, requestMessage);
                String username = "username";
                String password = "password";
                String encoded = Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
                requestMessage.Headers.Add("Authorization", "Basic " + encoded);
                requestMessage.RequestUri = targetUri;
                requestMessage.Headers.Host = targetUri.Host;
                requestMessage.Method = GetMethod(context.Request.Method);
                return requestMessage;
            private void CopyFromOriginalRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage)
                var requestMethod = context.Request.Method;
                if (!HttpMethods.IsGet(requestMethod) &&
                  !HttpMethods.IsHead(requestMethod) &&
                  !HttpMethods.IsDelete(requestMethod) &&
                    var streamContent = new StreamContent(context.Request.Body);
                    requestMessage.Content = streamContent;
                foreach (var header in context.Request.Headers)
                    requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
            private void CopyFromTargetResponseHeaders(HttpContext context, HttpResponseMessage responseMessage)
                foreach (var header in responseMessage.Headers)
                    context.Response.Headers[header.Key] = header.Value.ToArray();
                foreach (var header in responseMessage.Content.Headers)
                    context.Response.Headers[header.Key] = header.Value.ToArray();
            private static HttpMethod GetMethod(string method)
                if (HttpMethods.IsDelete(method)) return HttpMethod.Delete;
                if (HttpMethods.IsGet(method)) return HttpMethod.Get;
                if (HttpMethods.IsHead(method)) return HttpMethod.Head;
                if (HttpMethods.IsOptions(method)) return HttpMethod.Options;
                if (HttpMethods.IsPost(method)) return HttpMethod.Post;
                if (HttpMethods.IsPut(method)) return HttpMethod.Put;
                if (HttpMethods.IsTrace(method)) return HttpMethod.Trace;
                return new HttpMethod(method);
            private Uri BuildTargetUri(HttpRequest request)
                Uri targetUri = new Uri("https://Example.com/msmdpump.dll");
                return targetUri;

    As you can see I am taking the original request changing the target, adding credentials then returning the response.

    This is where the block seems to be on large requests:

    await responseMessage.Content.CopyToAsync(context.Response.Body);

    This is going to be MiddelWare in my application. For completeness my startupclass has this:

     app.Map("/api/test", api =>

    Can anyone tell me if this can be optimised further to deal with large responses?

    Really appreciate any help.


    • Moved by CoolDadTx Thursday, April 23, 2020 1:27 PM ASP.NET related
    Wednesday, April 22, 2020 2:27 PM

All replies

  • ASP.NET Core can be discussed in the ASP.NET forums.


    Wednesday, April 22, 2020 11:42 PM
  • Thanks reposted
    Thursday, April 23, 2020 12:41 AM