microsoft / microsoft/aspire

Aspire localhost TLD (*.dev.localhost) URLs break Codespaces port forwarding

Open
#14,236 0 comments 0 reactions 1 assignee Claimed by @mitchdenny View on GitHub
area-app-model
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

## Summary

When using Aspire's `--localhost-tld` option (which creates URLs like `https://myapp.dev.localhost:17000`), the terminal URL detection in GitHub Codespaces fails to automatically forward ports. Users must manually forward ports through the Codespaces UI.

## Reproduction Steps

1. Create a new Aspire project in a GitHub Codespace with the localhost TLD option enabled:
```bash
aspire new --localhost-tld
```
2. Run the project:
```bash
dotnet run --project MyApp.AppHost
```
3. Observe the terminal output displays URLs like:
```
Now listening on: https://myapp-apphost.dev.localhost:17000
Login to the dashboard at https://myapp-apphost.dev.localhost:17000/login?t=...
```
4. **Expected:** Codespaces should auto-detect the localhost URL and offer to forward the port
5. **Actual:** No port forwarding is triggered; the URL is not clickable/accessible

## Root Cause

The `CodespacesResourceUrlRewriterService` only rewrites URLs when the host is **exactly** `"localhost"`:

```csharp
// src/Aspire.Hosting/Devcontainers/Codespaces/CodespacesResourceUrlRewriterService.cs:36
if (!originalUrlSnapshot.IsInternal && (uri.Scheme == "http" || uri.Scheme == "https") && uri.Host == "localhost")
```

When `--localhost-tld` is enabled, the dashboard URL becomes `https://myproject-apphost.dev.localhost:17000`. This **does not match** the `uri.Host == "localhost"` condition because `uri.Host` is `myproject-apphost.dev.localhost`, not `localhost`.

As a result:
1. The Codespaces URL rewriter skips these URLs
2. The terminal outputs `*.dev.localhost` URLs unchanged
3. Codespaces' terminal URL detection doesn't recognize these as localhost URLs
4. Port forwarding is not triggered automatically

## Proposed Fix

Use the existing `EndpointHostHelpers.IsLocalhostOrLocalhostTld()` helper method which already handles all localhost variants:

```csharp
// Before (line 36):
if (!originalUrlSnapshot.IsInternal && (uri.Scheme == "http" || uri.Scheme == "https") && uri.Host == "localhost")

// After:
if (!originalUrlSnapshot.IsInternal && (uri.Scheme == "http" || uri.Scheme == "https")
&& EndpointHostHelpers.IsLocalhostOrLocalhostTld(uri))
```

This is a minimal, single-line change that leverages existing infrastructure.

## Affected Files

- `src/Aspire.Hosting/Devcontainers/Codespaces/CodespacesResourceUrlRewriterService.cs` (primary)
- Possibly `src/Aspire.Hosting/Devcontainers/Codespaces/CodespacesUrlRewriter.cs` if called from other paths

## Alternative Considerations

1. **Auto-disable `--localhost-tld` in Codespaces**: Detect the environment and warn or fallback to regular localhost URLs
2. **Documentation**: Document that `--localhost-tld` doesn't work optimally in Codespaces (not ideal UX)
3. **Hybrid display**: Show both Codespaces URL and original `.dev.localhost` URL in terminal

## Environment

- Aspire version: main branch / .NET 10
- Environment: GitHub Codespaces
- Feature: `--localhost-tld` template option

## Additional Context

- The `.localhost` TLD is an IETF reserved TLD (RFC 2606) that always resolves to `127.0.0.1`
- Browsers and OS handle `.localhost` specially, but port forwarding tools (including Codespaces) often only look for exact `localhost` matches
- The helper method `EndpointHostHelpers.IsLocalhostOrLocalhostTld()` already exists in the codebase for this exact purpose

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.