反向代理/跨域的 SignalR 连接问题
SignalR connectivity issue with reverse proxy / cross domains
我在 Azure(公司服务应用程序)的 Owin Web API 应用程序 运行 中托管了一个 SignalR 服务器和 运行。从一个单独的 Web 应用程序,假设应用程序 A(非 Azure)我正在使用 javascript 生成的代理连接到 SignalR:
CompanyServiceBaseUrl 设置为我的站点 url:(例如 "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>
这是我在客户端生成的文件夹结构:
当我在本地测试时,SignalR 连接工作正常,但当我在 Azure 托管的环境中测试时,连接失败。
SignalR 协商请求(在 App A 和 CompanyService 之间):
http://<mysiteurl>/signalr/negotiate
(请注意 URL:
中缺少 companyservice
应该是:
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 但没有成功。
这里有一个相关的 post 有跨域问题:
How do I get a SignalR hub connection to work cross-domain?
四个月后,一位同事提出了一个完美的解决方案。他的想法是创建一个自定义 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);
});
}
感谢我的同事 Jake S。
我在 Azure(公司服务应用程序)的 Owin Web API 应用程序 运行 中托管了一个 SignalR 服务器和 运行。从一个单独的 Web 应用程序,假设应用程序 A(非 Azure)我正在使用 javascript 生成的代理连接到 SignalR:
CompanyServiceBaseUrl 设置为我的站点 url:(例如 "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>
这是我在客户端生成的文件夹结构:
当我在本地测试时,SignalR 连接工作正常,但当我在 Azure 托管的环境中测试时,连接失败。
SignalR 协商请求(在 App A 和 CompanyService 之间):
http://<mysiteurl>/signalr/negotiate
(请注意 URL:
应该是:
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 但没有成功。
这里有一个相关的 post 有跨域问题:
How do I get a SignalR hub connection to work cross-domain?
四个月后,一位同事提出了一个完美的解决方案。他的想法是创建一个自定义 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);
});
}
感谢我的同事 Jake S。