反向代理/跨域的SignalR连接问题

时间:2015-09-25 14:03:51

标签: c# signalr reverse-proxy signalr-hub

我在Azure(公司服务应用程序)中运行的Owin Web API应用程序中托管并运行SignalR服务器。从单独的Web应用程序,假设应用程序A(非Azure)我使用javascript生成的代理连接到SignalR:

如果CompanyServiceBaseUrl设置为我的网站网址:(例如“http:// mysite / companyservice”)

    <script src="@Url.Content(CompanyServiceBaseUrl + "/Scripts/jquery.signalR-2.2.0.js")"></script>
    <script src="@Url.Content(CompanyServiceBaseUrl + "/signalr/hubs")" type="text/javascript"></script>

    <script type="text/javascript">
    var hub = $.connection.perform;

    hub.client.onToast = function () {
        $("#copyOrganizationSuccessAlert").show();
    };

    $(document).ready(function() {
        var event = document.createEvent('Event');
        event.initEvent('onOrganizationLock', true, true);

        onOrganizationLockEvent = function() {
            document.dispatchEvent(event);
        };

        hub.client.onOrganizationLock = onOrganizationLockEvent;
    });

    $.connection.hub.start().done(function () {
        hub.server.joinGroup(perform.company.application.clientId);
    });
</script>

这是我在客户端生成的文件夹结构:

enter image description here

当我在本地测试时,SignalR连接工作正常,但是当我在Azure环境中托管的环境中测试失败时。

SignalR协商请求(在App A和CompanyService之间):

http://<mysiteurl>/signalr/negotiate(请注意,网址中缺少公司服务:

应该是:

http://<mysiteurl>/companyservice/signalr/negotiate

这里是反向代理规则:

   <rule name="companyservice" stopProcessing="true"> 
      <match url="^companyservice/(.*)" /> 
      <conditions> 
        <add input="{CACHE_URL}" pattern="^(https?)://" /> 
      </conditions> 
      <action type="Rewrite" url="https://myazuresite.azurewebsites.net/{R:1}" /> 
      <serverVariables> 
        <set name="HTTP_ACCEPT_ENCODING" value="" /> 
      </serverVariables> 
    </rule> 
  </rules>

问题:

为什么我的客户端connection.Url在使用反向代理使用我的Azure站点进行测试时以“/ signalr”而不是“/ companyservice / signalr”的形式出现?

最后,看看这个报告的SignalR问题,看起来他的体验非常相似:

SignalR doesn't work behind a Reverse Proxy

但我想了解他的意思:

如果我使用反向代理规则(扫描和替换)并设置”Url“:”/ NorthboundWebApiClient / signalr“一切正常。

我已尝试建立连接with and without generated proxies手动指定我的连接URL var connection = $.hubConnection('/companyservice/signalr', {useDefaultPath: false});,在客户端配置CORS并且没有运气。

以下是跨网域问题的相关帖子:

How do I get a SignalR hub connection to work cross-domain?

1 个答案:

答案 0 :(得分:1)

四个月后,一位同事提出了一个完美的解决方案。他的想法是创建一个自定义自定义OwinMiddleware,将缺少的Azure虚拟目录添加到路径中以防丢失。像这样:

public class SignalRvDirMiddleware : OwinMiddleware
{
   public SignalRvDirMiddleware(OwinMiddleware next)
    : base(next)
   { }

   public override async Task Invoke(IOwinContext context)
   {
       var vdir = new PathString("/companyservice");
       PathString path = context.Request.PathBase;
       if (!path.StartsWithSegments(vdir))
       {
          context.Request.PathBase = vdir + path;
       }
       await Next.Invoke(context);
    }
 }

然后将它连接到Startup.cs上的Owin配置方法:

    public void Configuration(IAppBuilder appBuilder)
    {
        // Branch the pipeline here for requests that start with "/signalr"
        appBuilder.Map("/signalr", map =>
        {
            map.Use<SignalRvDirMiddleware>();
            map.RunSignalR(hubConfiguration);
        });
     }

归功于我的同事杰克S.