.NET Core reverse proxy middleware and signalR

I need to do a reverse proxy middleware in ASP.NET Core. I have something like this. But it doesn’t work with SignalR.

Reverse proxy has address 192.168.187.72:5000; SignalR 192.168.187.62:5000. Client connects to proxy, proxy changes the url to SignalR hub url, but in client I always get this error:

The server disconnected before the handshake could be started

Code:

public ReverseProxyMiddleware(RequestDelegate nextMiddleware,ILogger<ReverseProxyMiddleware> logger)
{
    _nextMiddleware = nextMiddleware;
    _logger = logger;
}

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);
         }

         return;
    }

    await _nextMiddleware(context);
}

private HttpRequestMessage CreateTargetMessage(HttpContext context, Uri targetUri)
{
    var requestMessage = new HttpRequestMessage();

    CopyFromOriginalRequestContentAndHeaders(context, requestMessage);

    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;
       
    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();
    }

    context.Response.Headers.Remove("transfer-encoding");
}

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 = null;
    StringValues clientId = string.Empty;

    targetUri = new Uri($"http://192.168.187.62:5000{request.Path}{request.QueryString}");

    _logger.LogInformation($"Request URL {request.Host + request.Path + request.QueryString} Target URL {targetUri.ToString()}");

    return targetUri;
}

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Are you sure you want to create such functionality manually?

There are many great libraries for reverse proxying, Microsoft has a new project called YARP (https://microsoft.github.io/reverse-proxy/) which is an open source reverse proxy told to be high performance and highly customizable.

If you like I can show you a sample how you can use yarp in an ASP.NET Core app.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x