Skip to content

Commit

Permalink
Merge pull request #1043 from Particular/sc-redirect-support
Browse files Browse the repository at this point in the history
support redirect when connecting to ServiceControl instances
  • Loading branch information
HEskandari authored Apr 28, 2021
2 parents 16824e0 + f91ae04 commit 8e3a86a
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 26 deletions.
18 changes: 13 additions & 5 deletions src/ServiceInsight.Tests/ServiceControlConnectionDialogTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ public class ServiceControlConnectionDialogTests
ServiceControlClientRegistry clientRegistry;
ProfilerSettings storedSetting;
ServiceControlConnectionViewModel connectTo;
IServiceControl serviceControl;

[SetUp]
public void TestInitialize()
{
shell = Substitute.For<ShellViewModel>();
//serviceControl = Substitute.For<IServiceControl>();
settingsProvider = Substitute.For<ISettingsProvider>();
//connection = Substitute.For<ServiceControlConnectionProvider>();
serviceControl = Substitute.For<IServiceControl>();
clientRegistry = Substitute.For<ServiceControlClientRegistry>();
clientRegistry.Create(Arg.Any<string>()).Returns(serviceControl);
storedSetting = GetReloadedSettings();
settingsProvider.GetSettings<ProfilerSettings>().Returns(storedSetting);
connectTo = new ServiceControlConnectionViewModel(settingsProvider, clientRegistry) { Parent = shell };
Expand All @@ -36,8 +37,11 @@ public void TestInitialize()
[Test]
public async Task Should_be_able_to_connect_to_a_valid_service()
{
var url = "http://localhost:8080/managementApi";
serviceControl.IsAlive().Returns((true, url));
serviceControl.GetVersion().Returns((url, url));
((IActivate)connectTo).Activate();
connectTo.ServiceUrl = "http://localhost:8080/managemnetApi";
connectTo.ServiceUrl = url;
await connectTo.Accept();

connectTo.CanAccept().ShouldBe(true);
Expand All @@ -47,13 +51,17 @@ public async Task Should_be_able_to_connect_to_a_valid_service()
[Test]
public async Task Should_store_connection_address_and_add_it_to_recent_entries()
{
var url = "http://localhost:8080/managementApi";
serviceControl.IsAlive().Returns((true, url));
serviceControl.GetVersion().Returns((url, url));

((IActivate)connectTo).Activate();
connectTo.ServiceUrl = "http://localhost:8080/managemnetApi";
connectTo.ServiceUrl = url;
await connectTo.Accept();

settingsProvider.Received().SaveSettings(Arg.Any<ProfilerSettings>());
storedSetting.RecentServiceControlEntries.Count.ShouldBe(3);
storedSetting.RecentServiceControlEntries.ShouldContain("http://localhost:8080/managemnetApi");
storedSetting.RecentServiceControlEntries.ShouldContain(url);
}

ProfilerSettings GetReloadedSettings()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,21 +168,24 @@ public async Task ConnectToService(string url)
}

var available = false;
using (workNotifier.NotifyOfWork($"Verifying ServiceControl availability at {url}"))
var address = url;

using (workNotifier.NotifyOfWork($"Verifying ServiceControl availability at {address}"))
{
clientRegistry.EnsureServiceControlClient(url);
var serviceControl = clientRegistry.GetServiceControl(url);
available = await serviceControl.IsAlive();
var serviceControl = clientRegistry.Create(url);
(available, address) = await serviceControl.IsAlive();
}

if (!available)
{
return;
}

using (workNotifier.NotifyOfWork($"Connecting to ServiceControl at {url}"))
clientRegistry.EnsureServiceControlClient(address);

using (workNotifier.NotifyOfWork($"Connecting to ServiceControl at {address}"))
{
var node = AddServiceNode(url);
var node = AddServiceNode(address);
await RefreshEndpoints(node);
ExpandServiceControlNode(node);
SelectDefaultEndpoint(node);
Expand Down
37 changes: 30 additions & 7 deletions src/ServiceInsight/ServiceControl/DefaultServiceControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,48 @@ public DefaultServiceControl(
cache = new MemoryCache("ServiceControlReponses", new NameValueCollection(1) { { "cacheMemoryLimitMegabytes", settings.CacheSize.ToString() } });
}

public async Task<bool> IsAlive()
public async Task<(bool, string)> IsAlive()
{
var version = await GetVersion().ConfigureAwait(false);
var (version, address) = await GetVersion().ConfigureAwait(false);

if (version != null)
{
RaygunUtility.LastServiceControlVersion = version;
}

return version != null;
return (version != null, address);
}

public async Task<string> GetVersion()
public async Task<(string, string)> GetVersion()
{
var request = new RestRequestWithCache(RestRequestWithCache.CacheStyle.Immutable);
var restClient = CreateClient();
restClient.FollowRedirects = false;

var header = await Execute(request, restResponse => restResponse.Headers.SingleOrDefault(x => x.Name == ServiceControlHeaders.ParticularVersion)).ConfigureAwait(false);
LogRequest(request);

var address = restClient.BaseUrl.ToString();
var response = await restClient.ExecuteAsync(request);

CleanResponse(response);

if (response.StatusCode == HttpStatusCode.Redirect ||
response.StatusCode == HttpStatusCode.TemporaryRedirect ||
response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.Found)
{
var location = response.Headers.SingleOrDefault(h => string.Equals(h.Name, "Location", StringComparison.OrdinalIgnoreCase));
if (location?.Value != null)
{
address = location.Value.ToString();
var redirectedClient = CreateClient(address);
response = await redirectedClient.ExecuteAsync(request);
}
}

var header = response.Headers.SingleOrDefault(x => x.Name == ServiceControlHeaders.ParticularVersion);

return header?.Value.ToString();
return (header?.Value?.ToString(), address);
}

Task<ServiceControlRootUrls> GetRootUrls()
Expand Down Expand Up @@ -359,7 +382,7 @@ static RestRequestWithCache CreateMessagesRequest(string endpointName = null) =>
PrevLink = prev,
LastLink = last,
FirstLink = first,
TotalCount = int.Parse(response.Headers.First(x => x.Name == ServiceControlHeaders.TotalCount).Value.ToString()),
TotalCount = int.Parse(response.Headers.Single(x => x.Name == ServiceControlHeaders.TotalCount).Value.ToString()),
PageSize = pageSize
};
},
Expand Down
4 changes: 2 additions & 2 deletions src/ServiceInsight/ServiceControl/IServiceControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ namespace ServiceInsight.ServiceControl

public interface IServiceControl
{
Task<bool> IsAlive();
Task<(bool, string)> IsAlive();

Task<string> GetVersion();
Task<(string, string)> GetVersion();

Task RetryMessage(string messageId, string instanceId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@ public void EnsureServiceControlClient(string serviceUrl)

if (!serviceControlClientCache.ContainsKey(normalizeUrl))
{
var serviceControl = serviceControlFactory(normalizeUrl);
var serviceControl = Create(normalizeUrl);
serviceControlClientCache.TryAdd(normalizeUrl, serviceControl);
}
}

public IServiceControl Create(string url)
{
var serviceControl = serviceControlFactory(url);
return serviceControl;
}

public void RemoveServiceControlClient(string serviceUrl)
{
if (!serviceUrl.IsValidUrl())
Expand Down Expand Up @@ -66,7 +72,7 @@ public virtual async Task<IEnumerable<string>> GetVersions()
var versions = new List<string>();
foreach (var entry in serviceControlClientCache)
{
var version = await entry.Value.GetVersion();
var (version, _) = await entry.Value.GetVersion();
versions.Add(version);
}
return versions;
Expand Down
12 changes: 8 additions & 4 deletions src/ServiceInsight/Shell/ServiceControlConnectionViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,21 @@ async Task<bool> IsValid(string serviceUrl)

if (valid)
{
clientRegistry.EnsureServiceControlClient(serviceUrl);
var service = clientRegistry.GetServiceControl(serviceUrl);
var address = serviceUrl;
var service = clientRegistry.Create(address);

Version = await service.GetVersion();
(Version, address) = await service.GetVersion();

if (Version == null)
{
clientRegistry.RemoveServiceControlClient(serviceUrl);
clientRegistry.RemoveServiceControlClient(address);
ErrorMessage = certValidationFailed ? CertValidationErrorMessage : ConnectionErrorMessage;
valid = false;
}
else
{
clientRegistry.EnsureServiceControlClient(address);
}
}

return valid;
Expand Down

0 comments on commit 8e3a86a

Please sign in to comment.