我在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>
这是我在客户端生成的文件夹结构:
当我在本地测试时,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并且没有运气。
以下是跨网域问题的相关帖子:
答案 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.