-
Notifications
You must be signed in to change notification settings - Fork 526
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite dashboard URL in the console. (#6591)
* Rewrite dashboard URL in the console. * Include launch.json (and add Copilot extension). * Can't get serverReadyAction working. * Fix compiler error. * PR feedback.
- Loading branch information
1 parent
9d06327
commit bcfa2df
Showing
8 changed files
with
130 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"request": "launch", | ||
"name": "C#: WaitFor (Debug)", | ||
"type": "dotnet", | ||
"projectPath": "${workspaceFolder}/playground/waitfor/WaitForSandbox.AppHost/WaitForSandbox.AppHost.csproj" | ||
} | ||
] | ||
} |
76 changes: 76 additions & 0 deletions
76
src/Aspire.Hosting/Codespaces/CodespacesResourceUrlRewriterService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections.Immutable; | ||
using Aspire.Hosting.ApplicationModel; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Aspire.Hosting.Codespaces; | ||
|
||
internal sealed class CodespacesResourceUrlRewriterService(ILogger<CodespacesResourceUrlRewriterService> logger, IOptions<CodespacesOptions> options, CodespacesUrlRewriter codespaceUrlRewriter, ResourceNotificationService resourceNotificationService) : BackgroundService | ||
{ | ||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | ||
{ | ||
if (!options.Value.IsCodespace) | ||
{ | ||
logger.LogTrace("Not running in Codespaces, skipping URL rewriting."); | ||
return; | ||
} | ||
|
||
do | ||
{ | ||
try | ||
{ | ||
var resourceEvents = resourceNotificationService.WatchAsync(stoppingToken); | ||
|
||
await foreach (var resourceEvent in resourceEvents.ConfigureAwait(false)) | ||
{ | ||
Dictionary<UrlSnapshot, UrlSnapshot>? remappedUrls = null; | ||
|
||
foreach (var originalUrlSnapshot in resourceEvent.Snapshot.Urls) | ||
{ | ||
var uri = new Uri(originalUrlSnapshot.Url); | ||
|
||
if (!originalUrlSnapshot.IsInternal && (uri.Scheme == "http" || uri.Scheme == "https") && uri.Host == "localhost") | ||
{ | ||
remappedUrls ??= new(); | ||
|
||
var newUrlSnapshot = originalUrlSnapshot with | ||
{ | ||
// The format of GitHub Codespaces URLs comprises the codespace | ||
// name (from the CODESPACE_NAME environment variable, the port, | ||
// and the port forwarding domain (via GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN | ||
// which is typically ".app.github.dev". The VSCode instance is typically | ||
// hosted at codespacename.github.dev whereas the forwarded ports | ||
// would be at codespacename-port.app.github.dev. | ||
Url = codespaceUrlRewriter.RewriteUrl(uri) | ||
}; | ||
|
||
remappedUrls.Add(originalUrlSnapshot, newUrlSnapshot); | ||
} | ||
} | ||
|
||
if (remappedUrls is not null) | ||
{ | ||
var transformedUrls = from originalUrl in resourceEvent.Snapshot.Urls | ||
select remappedUrls.TryGetValue(originalUrl, out var remappedUrl) ? remappedUrl : originalUrl; | ||
|
||
await resourceNotificationService.PublishUpdateAsync(resourceEvent.Resource, resourceEvent.ResourceId, s => s with | ||
{ | ||
Urls = transformedUrls.ToImmutableArray() | ||
}).ConfigureAwait(false); | ||
} | ||
} | ||
} | ||
catch (Exception ex) when (!stoppingToken.IsCancellationRequested) | ||
{ | ||
// When debugging sometimes we'll get cancelled here but we don't want | ||
// to tear down the loop. We only want to crash out when the service's | ||
// cancellation token is signaled. | ||
logger.LogTrace(ex, "Codespace URL rewriting loop threw an exception but was ignored."); | ||
} | ||
} while (!stoppingToken.IsCancellationRequested); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,32 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections.Immutable; | ||
using Aspire.Hosting.ApplicationModel; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Aspire.Hosting.Codespaces; | ||
|
||
internal sealed class CodespacesUrlRewriter(ILogger<CodespacesUrlRewriter> logger, IOptions<CodespacesOptions> options, ResourceNotificationService resourceNotificationService) : BackgroundService | ||
internal sealed class CodespacesUrlRewriter(IOptions<CodespacesOptions> options) | ||
{ | ||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | ||
public string RewriteUrl(string url) | ||
{ | ||
ArgumentNullException.ThrowIfNullOrWhiteSpace(url); | ||
|
||
if (!options.Value.IsCodespace) | ||
{ | ||
logger.LogTrace("Not running in Codespaces, skipping URL rewriting."); | ||
return; | ||
return url; | ||
} | ||
|
||
do | ||
{ | ||
try | ||
{ | ||
var resourceEvents = resourceNotificationService.WatchAsync(stoppingToken); | ||
|
||
await foreach (var resourceEvent in resourceEvents.ConfigureAwait(false)) | ||
{ | ||
Dictionary<UrlSnapshot, UrlSnapshot>? remappedUrls = null; | ||
|
||
foreach (var originalUrlSnapshot in resourceEvent.Snapshot.Urls) | ||
{ | ||
var uri = new Uri(originalUrlSnapshot.Url); | ||
|
||
if (!originalUrlSnapshot.IsInternal && (uri.Scheme == "http" || uri.Scheme == "https") && uri.Host == "localhost") | ||
{ | ||
remappedUrls ??= new(); | ||
|
||
var newUrlSnapshot = originalUrlSnapshot with | ||
{ | ||
// The format of GitHub Codespaces URLs comprises the codespace | ||
// name (from the CODESPACE_NAME environment variable, the port, | ||
// and the port forwarding domain (via GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN | ||
// which is typically ".app.github.dev". The VSCode instance is typically | ||
// hosted at codespacename.github.dev whereas the forwarded ports | ||
// would be at codespacename-port.app.github.dev. | ||
Url = $"{uri.Scheme}://{options.Value.CodespaceName}-{uri.Port}.{options.Value.PortForwardingDomain}{uri.AbsolutePath}" | ||
}; | ||
|
||
remappedUrls.Add(originalUrlSnapshot, newUrlSnapshot); | ||
} | ||
} | ||
return RewriteUrl(new Uri(url, UriKind.Absolute)); | ||
} | ||
|
||
if (remappedUrls is not null) | ||
{ | ||
var transformedUrls = from originalUrl in resourceEvent.Snapshot.Urls | ||
select remappedUrls.TryGetValue(originalUrl, out var remappedUrl) ? remappedUrl : originalUrl; | ||
public string RewriteUrl(Uri uri) | ||
{ | ||
if (!options.Value.IsCodespace) | ||
{ | ||
return uri.ToString(); | ||
} | ||
|
||
await resourceNotificationService.PublishUpdateAsync(resourceEvent.Resource, resourceEvent.ResourceId, s => s with | ||
{ | ||
Urls = transformedUrls.ToImmutableArray() | ||
}).ConfigureAwait(false); | ||
} | ||
} | ||
} | ||
catch (Exception ex) when (!stoppingToken.IsCancellationRequested) | ||
{ | ||
// When debugging sometimes we'll get cancelled here but we don't want | ||
// to tear down the loop. We only want to crash out when the service's | ||
// cancellation token is signaled. | ||
logger.LogTrace(ex, "Codespace URL rewriting loop threw an exception but was ignored."); | ||
} | ||
} while (!stoppingToken.IsCancellationRequested); | ||
var codespacesUrl = $"{uri.Scheme}://{options.Value.CodespaceName}-{uri.Port}.{options.Value.PortForwardingDomain}{uri.AbsolutePath}"; | ||
return codespacesUrl; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters