Skip to content

Commit b2670fe

Browse files
authored
Fix proxy not applied to serverless transient mode (#1708)
Fix #1700
1 parent 5826b42 commit b2670fe

File tree

6 files changed

+60
-19
lines changed

6 files changed

+60
-19
lines changed

src/Microsoft.Azure.SignalR.Management/DependencyInjectionExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ private static IServiceCollection TrySetProductInfo(this IServiceCollection serv
123123
}
124124

125125
private static IServiceCollection AddRestClientFactory(this IServiceCollection services) => services
126-
.AddHttpClient()
126+
.AddHttpClient(Options.DefaultName)
127+
.ConfigurePrimaryHttpMessageHandler(sp => new HttpClientHandler() { Proxy = sp.GetRequiredService<IOptions<ServiceManagerOptions>>().Value.Proxy }).Services
127128
.AddSingleton(sp =>
128129
{
129130
var options = sp.GetRequiredService<IOptions<ServiceManagerOptions>>().Value;

test/Microsoft.Azure.SignalR.Management.Tests/DependencyInjectionExtensionFacts.cs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.IO;
67
using System.Linq;
8+
using System.Net;
79
using System.Reflection;
810
using System.Threading.Tasks;
11+
using Microsoft.AspNetCore.Builder;
12+
using Microsoft.AspNetCore.Hosting.Server;
13+
using Microsoft.AspNetCore.Hosting.Server.Features;
14+
using Microsoft.AspNetCore.Http;
915
using Microsoft.Azure.SignalR.Tests.Common;
1016
using Microsoft.Extensions.Configuration;
1117
using Microsoft.Extensions.DependencyInjection;
18+
using Microsoft.Extensions.Logging;
1219
using Microsoft.Extensions.Options;
1320
using Newtonsoft.Json;
1421
using Xunit;
@@ -33,7 +40,7 @@ public DependencyInjectionExtensionFacts(ITestOutputHelper outputHelper)
3340
public async Task FileConfigHotReloadTest()
3441
{
3542
// to avoid possible file name conflict with another FileConfigHotReloadTest
36-
string configPath = nameof(DependencyInjectionExtensionFacts);
43+
var configPath = nameof(DependencyInjectionExtensionFacts);
3744
var originUrl = "http://origin.url";
3845
var newUrl = "http://new.url";
3946
var configObj = new
@@ -47,7 +54,7 @@ public async Task FileConfigHotReloadTest()
4754
}
4855
};
4956
File.WriteAllText(configPath, JsonConvert.SerializeObject(configObj));
50-
ServiceCollection services = new ServiceCollection();
57+
var services = new ServiceCollection();
5158
services.AddSignalRServiceManager();
5259
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().AddJsonFile(configPath, false, true).Build());
5360
using var provider = services.BuildServiceProvider();
@@ -170,7 +177,7 @@ public void ConnectionStringNull_TransientMode_Throw()
170177
public async Task MultiServiceEndpoints_NotAppliedToTransientModeAsync()
171178
{
172179
// to avoid possible file name conflict with another FileConfigHotReloadTest
173-
string configPath = nameof(MultiServiceEndpoints_NotAppliedToTransientModeAsync);
180+
var configPath = nameof(MultiServiceEndpoints_NotAppliedToTransientModeAsync);
174181
var connStr = FakeEndpointUtils.GetFakeConnectionString(1).Single();
175182
var configObj = new
176183
{
@@ -208,5 +215,38 @@ public async Task MultiServiceEndpoints_NotAppliedToTransientModeAsync()
208215
await Task.Delay(5000);
209216
Assert.Equal(connStr, optionsMonitor.CurrentValue.ConnectionString);// as new config don't pass validation, it is not reloaded
210217
}
218+
219+
[Fact]
220+
public async Task ProxyApplyToTransientModeTestAsync()
221+
{
222+
var requestUrls = new Queue<string>();
223+
224+
//create a simple proxy server
225+
var appBuilder = WebApplication.CreateBuilder();
226+
appBuilder.Services.AddLogging(b => b.AddXunit(_outputHelper));
227+
using var app = appBuilder.Build();
228+
//randomly choose a free port, listen to all interfaces
229+
app.Urls.Add("http://[::1]:0");
230+
app.Run(async context =>
231+
{
232+
requestUrls.Enqueue(context.Request.Path);
233+
await context.Response.WriteAsync("");
234+
});
235+
await app.StartAsync();
236+
237+
var serviceManager = new ServiceManagerBuilder().WithOptions(o =>
238+
{
239+
// use http schema to avoid SSL handshake
240+
o.ConnectionString = "Endpoint=http://abc;AccessKey=nOu3jXsHnsO5urMumc87M9skQbUWuQ+PE5IvSUEic8w=;Version=1.0;";
241+
o.Proxy = new WebProxy(app.Services.GetRequiredService<IServer>().Features.Get<IServerAddressesFeature>().Addresses.First());
242+
}).BuildServiceManager();
243+
Assert.True(await serviceManager.IsServiceHealthy(default));
244+
Assert.Equal("/api/v1/health", requestUrls.Dequeue());
245+
246+
using var hubContext = await serviceManager.CreateHubContextAsync("hub", default);
247+
Assert.True(await hubContext.ClientManager.UserExistsAsync("userId"));
248+
Assert.Equal("/api/hubs/hub/users/userId", requestUrls.Dequeue());
249+
await app.StopAsync();
250+
}
211251
}
212252
}

test/Microsoft.Azure.SignalR.Management.Tests/Microsoft.Azure.SignalR.Management.Tests.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net5.0</TargetFramework>
5-
4+
<TargetFramework>net6.0</TargetFramework>
65
<IsPackable>false</IsPackable>
76
</PropertyGroup>
87

test/Microsoft.Azure.SignalR.Management.Tests/RestHealthCheckServiceFacts.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ public async Task TestRestHealthCheckServiceWithEndpointFromHealthyToUnhealthy()
6464
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway))
6565
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway))
6666
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadGateway));
67-
67+
6868
var checkInterval = TimeSpan.FromSeconds(3);
6969
var retryInterval = TimeSpan.FromSeconds(0.5);
7070
using var _ = StartLog(out var loggerFactory);
7171
var services = new ServiceCollection()
72-
.AddHttpClient(Options.DefaultName).ConfigurePrimaryHttpMessageHandler(() => handlerMock.Object).Services
7372
.AddSignalRServiceManager()
73+
.AddHttpClient(Options.DefaultName).ConfigurePrimaryHttpMessageHandler(() => handlerMock.Object).Services
7474
.Configure<HealthCheckOption>(o =>
7575
{
7676
o.CheckInterval = checkInterval;
@@ -84,7 +84,7 @@ public async Task TestRestHealthCheckServiceWithEndpointFromHealthyToUnhealthy()
8484
.CreateHubContextAsync(HubName, default);
8585

8686
var endpoint = (serviceHubContext as ServiceHubContextImpl).ServiceProvider.GetRequiredService<IServiceEndpointManager>().GetEndpoints(HubName).First();
87-
87+
8888
//The first health check is OK
8989
Assert.True(endpoint.Online);
9090

test/Microsoft.Azure.SignalR.Management.Tests/Serialization/SerailizerFacts.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using System.Text;
8+
using System.Text.Json.Serialization;
89
using System.Threading.Tasks;
910
using Azure.Core.Serialization;
1011
using Microsoft.AspNetCore.SignalR;
@@ -26,7 +27,7 @@ public static IEnumerable<object[]> IgnoreNullObjectSerializers
2627
{
2728
get
2829
{
29-
yield return new object[] { new JsonObjectSerializer(new() { IgnoreNullValues = true }) };
30+
yield return new object[] { new JsonObjectSerializer(new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }) };
3031
yield return new object[] { new NewtonsoftJsonObjectSerializer(new() { NullValueHandling = NullValueHandling.Ignore }) };
3132
}
3233
}

test/Microsoft.Azure.SignalR.Management.Tests/StronglyTypedServiceHubContextFacts.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ void assertion(HttpRequestMessage request, CancellationToken t)
114114
{
115115
Assert.EndsWith($"/groups/{groupName}/connections/{connectionId}?api-version=2022-06-01", request.RequestUri.AbsoluteUri);
116116
}
117-
var services = new ServiceCollection().AddHttpClient(Options.DefaultName)
118-
.ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(assertion)).Services
119-
.AddSignalRServiceManager();
117+
var services = new ServiceCollection()
118+
.AddSignalRServiceManager()
119+
.AddHttpClient(Options.DefaultName).ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(assertion)).Services;
120120
await using var hubContext = await Create(ServiceTransportType.Transient, services);
121121

122122
await hubContext.Groups.AddToGroupAsync(connectionId, groupName);
@@ -156,9 +156,9 @@ void assertion(HttpRequestMessage request, CancellationToken t)
156156
{
157157
Assert.EndsWith($"/users/{userId}/groups/{groupName}?api-version=2022-06-01", request.RequestUri.AbsoluteUri);
158158
}
159-
var services = new ServiceCollection().AddHttpClient(Options.DefaultName)
160-
.ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(assertion)).Services
161-
.AddSignalRServiceManager();
159+
var services = new ServiceCollection()
160+
.AddSignalRServiceManager()
161+
.AddHttpClient(Options.DefaultName).ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(assertion)).Services;
162162
await using var hubContext = await Create(ServiceTransportType.Transient, services);
163163

164164
await hubContext.UserGroups.AddToGroupAsync(userId, groupName);
@@ -198,9 +198,9 @@ void assertion(HttpRequestMessage request, CancellationToken t)
198198
Assert.EndsWith($"/connections/{connectionId}?api-version=2022-06-01", request.RequestUri.AbsoluteUri);
199199
Assert.Equal(HttpMethod.Delete, request.Method);
200200
}
201-
var services = new ServiceCollection().AddHttpClient(Options.DefaultName)
202-
.ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(assertion)).Services
203-
.AddSignalRServiceManager();
201+
var services = new ServiceCollection()
202+
.AddSignalRServiceManager()
203+
.AddHttpClient(Options.DefaultName).ConfigurePrimaryHttpMessageHandler(() => new TestRootHandler(assertion)).Services;
204204
await using var hubContext = await Create(ServiceTransportType.Transient, services);
205205

206206
await hubContext.ClientManager.CloseConnectionAsync(connectionId);

0 commit comments

Comments
 (0)