Skip to content

Add connect --emulator shortcut with HTTPS/HTTP fallback#76

Open
mkrueger wants to merge 2 commits intomainfrom
feat/connect-emulator-flag
Open

Add connect --emulator shortcut with HTTPS/HTTP fallback#76
mkrueger wants to merge 2 commits intomainfrom
feat/connect-emulator-flag

Conversation

@mkrueger
Copy link
Copy Markdown
Contributor

@mkrueger mkrueger commented May 6, 2026

Refs #74.

Reduces friction in using the shell with the Cosmos DB Emulator.

What

  • Adds a connect --emulator (alias -e) shortcut and a startup --connect-emulator option.
    • Defaults the endpoint to https://localhost:8081/ when no connection string is given.
    • Uses the well-known emulator key and gateway mode (existing behavior, just easier to invoke).
    • Refuses to be combined with non-local endpoints to keep behavior predictable.
  • On TLS handshake failure against an emulator endpoint, the shell now retries once over HTTP and reports which protocol was actually used.
  • When the connection ends up on HTTP, the shell prints a hint that the Cosmos DB emulator Docker image accepts --protocol [https|http], which lets users skip TLS cert setup entirely.

Why

Issue #74 tracks the rough first-use experience with the emulator: users have to deal with self-signed cert imports, switching protocols, and re-typing the well-known key/connection string. With this change the simplest path is now connect --emulator (or cosmosdbshell --connect-emulator) and we surface the HTTPS-vs-HTTP situation explicitly instead of silently failing.

Safety

The HTTPS → HTTP fallback is intentionally scoped: it only triggers when --emulator is used (or an emulator endpoint is auto-detected), the original scheme is HTTPS, and the failure is a TLS handshake / cert-validation error. We don't downgrade arbitrary HTTPS endpoints.

Validation

  • dotnet build CosmosDBShell/CosmosDBShell.csproj — green
  • dotnet test CosmosDBShell.Tests/CosmosDBShell.Tests.csproj --filter "Category!=Emulator" — 872 passed (4 new connect tests added)
  • Manual: connect --emulator shows up in help connect with the new example.

- New 'connect --emulator' (and '-e') flag and '--connect-emulator' startup option that default the endpoint to https://localhost:8081/ and use the well-known emulator key / gateway mode.
- On TLS handshake failure against a local emulator endpoint, the shell now retries once over HTTP and reports which protocol was actually used. When HTTP is used it points to the Cosmos DB emulator Docker image's '--protocol [https|http]' flag, which lets users skip TLS cert setup.
- Refusing '--emulator' against non-local endpoints to avoid silent HTTPS->HTTP downgrades on arbitrary hosts.
- Tests, docs (README, docs/connect.md) and en.ftl strings updated.
@mkrueger mkrueger requested review from a team and Copilot May 6, 2026 09:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the first-run experience for using CosmosDBShell with the Azure Cosmos DB Emulator by adding explicit emulator connection shortcuts and implementing an emulator-scoped HTTPS→HTTP fallback when TLS negotiation fails.

Changes:

  • Added connect --emulator / -e and startup --connect-emulator, defaulting to https://localhost:8081/ with emulator well-known key + gateway mode.
  • Implemented an emulator-only retry over HTTP when an HTTPS connection fails due to a detected TLS handshake/certificate problem, and prints which protocol was used.
  • Updated docs/localization and added tests for option binding and non-local endpoint rejection.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
README.md Documents the new --connect-emulator startup option.
docs/connect.md Adds emulator shortcut examples and explains protocol reporting/tip.
CosmosDBShell/Program.cs Wires --connect-emulator into startup connect flow.
CosmosDBShell/lang/en.ftl Adds localized strings for emulator option, errors, and protocol reporting.
CosmosDBShell/Azure.Data.Cosmos.Shell.Util/LocalizableSentenceBuilder.cs Exposes the localized help string for the new startup option.
CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Implements forceEmulator, endpoint defaulting, and HTTPS→HTTP fallback logic.
CosmosDBShell/Azure.Data.Cosmos.Shell.Commands/ConnectCommand.cs Adds --emulator / -e and routes it to ShellInterpreter.ConnectAsync.
CosmosDBShell.Tests/CommandTests/ConnectCommandTests.cs Adds tests for emulator flag binding and non-local endpoint rejection.
Comments suppressed due to low confidence (1)

CosmosDBShell/Azure.Data.Cosmos.Shell.Commands/ConnectCommand.cs:103

  • The JSON result for connect sets ["connected state"] based on the input ConnectionString. When using connect --emulator with no explicit endpoint this becomes null, and when an HTTPS→HTTP fallback occurs it will still report the original HTTPS endpoint rather than the actual connected endpoint. Consider using the post-connect state (e.g., ((ConnectedState)shell.State).Client.Endpoint) so the result reflects the real connection.
            var endpoint = this.ConnectionString is null
                ? null
                : ParsedDocDBConnectionString.ExtractEndpoint(this.ConnectionString);
            var resultElement = JsonSerializer.SerializeToElement(new Dictionary<string, string?>
            {
                ["connected state"] = endpoint,
            });

Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Commands/ConnectCommand.cs Outdated
- ParsedDocDBConnectionString.IsLocalEmulatorEndpoint now extracts the endpoint URL and matches the host exactly (case-insensitive 'localhost' or IPAddress.IsLoopback) instead of doing a substring match. This prevents bypasses like 'https://notlocalhost.com/' or 'https://contoso.localhost.com/'.
- ConnectWithAccountKeyAsync HTTP fallback now propagates OperationCanceledException when the user cancels mid-fallback, and aggregates both the original TLS exception and the fallback exception into an AggregateException so diagnostics surface the actual failure on the HTTP attempt instead of only the TLS error.
- IsTlsHandshakeFailure switched to type-based detection (AuthenticationException / CryptographicException / SocketException ConnectionReset|ConnectionAborted) instead of a 'SSL' substring match on the exception message; this avoids localized message brittleness and false positives.
- Tightened the connect --emulator example wording to match the actual behavior (HTTPS first, fall back to HTTP only on TLS handshake failure).
- Tests: added IsLocalEmulatorEndpoint host-match tests and IsTlsHandshakeFailure unit tests covering AuthenticationException, ConnectionReset, generic HttpRequestException with 'SSL' in message, and unrelated socket errors. 886 passing (+14).
@mkrueger mkrueger requested a review from sevoku May 7, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants