Change:
<!-- Do Not Delete This! featurerequesttemplate --<!-- Please read our Rules of Conduct: --<!-- Please search existing issues to avoid creating duplicates. --<!-- Describe the feature you'd like. --I'm using the 'Remote - SSH' extension. Suppose I set up static forwarding in my local : So port 3000 is statically forwarded to port 3000. Now if I output a link to the terminal (from within the remote), when this link is 'Command + Clicked', vscode opens in the browser - the wrong port, because it's auto-forwarded to the next available port. It feels like if static forwarding for this port is already set up, it could always infer that no auto port forwarding is needed and hence open in the browser at port 3000. The setting does not help in this case. Thanks :)
does the SSH extension use () to ensure that statically forwarded ports like this show in the ports view?
Yes
Thanks for confirming!
This looks like it will be a larger change. Moving to September.
Hi. Just encountered this problem today. I am using VSCode Docker remotes with Docker Desktop. One of my containers is running minio. There is a static port forward configured in that looks like this: My application sometimes prints out a full URL to the integrated terminal that looks like Clicking that link to open it in my web browser causes VSCode to dynamically forward a brand new port and rewrite the URL replacing the 9000 with something like . I would actually be ok with that, but that URL with the new port number doesn't even work. The original one does work. My situation sounds basically the same as OP, only using Docker remote instead of SSH remote. Just wanted to share my use case to verify it is actually the same issue and that whatever solution comes will solve it for both of us. I also want to say this feature was very unexpected. Personally, I think it should be off by default. URLs should be opened exactly as they are written. Please provide at least a setting so I can always open URLs from integrated terminal exactly as they appear. The back of my mind also wonders if there could be any potential security implication of rewriting URLs this way. Thanks.

Discussion:
canTunnel(uri: URI): boolean; openTunnel(addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded?: boolean, privacy?: string, protocol?: string): Promise<RemoteTunnel | undefined> | undefined; <ins> getExistingTunnel(remoteHost: string, remotePort: number): Promise<RemoteTunnel | undefined>; </ins> setEnvironmentTunnel(remoteHost: string, remotePort: number, localAddress: string, privacy: string, protocol: string): void; closeTunnel(remoteHost: string, remotePort: number): Promise<void>; setTunnelProvider(provider: ITunnelProvider | undefined): IDisposable;

})); } <ins> async getExistingTunnel(remoteHost: string, remotePort: number): Promise<RemoteTunnel | undefined> { if (isAllInterfaces(remoteHost) || isLocalhost(remoteHost)) { remoteHost = LOCALHOST_ADDRESSES[0]; } const existing = this.getTunnelFromMap(remoteHost, remotePort); if (existing) { ++existing.refcount; return existing.value; } return undefined; } </ins> openTunnel(addressProvider: IAddressProvider | undefined, remoteHost: string | undefined, remotePort: number, localPort?: number, elevateIfNeeded: boolean = false, privacy?: string, protocol?: string): Promise<RemoteTunnel | undefined> | undefined { this.logService.trace(`ForwardedPorts: (TunnelService) openTunnel request for ${remoteHost}:${remotePort} on local port ${localPort}.`); if (!addressProvider) {

return (await this.remoteAuthorityResolverService.resolveAuthority(remoteAuthority)).authority; } } : undefined; <del> const tunnel = await this.tunnelService.openTunnel(addressProvider, portMappingRequest.address, portMappingRequest.port); </del> <ins> let tunnel = await this.tunnelService.getExistingTunnel(portMappingRequest.address, portMappingRequest.port); if (!tunnel) { tunnel = await this.tunnelService.openTunnel(addressProvider, portMappingRequest.address, portMappingRequest.port); } </ins> if (tunnel) { const addressAsUri = URI.parse(tunnel.localAddress); const resolved = addressAsUri.scheme.startsWith(uri.scheme) ? addressAsUri : uri.with({ authority: tunnel.localAddress }); return { resolved, <del> dispose: () => tunnel.dispose(), </del> <ins> dispose: () => tunnel?.dispose(), </ins> }; } }

this._register(this.tunnelService.onTunnelOpened(async (tunnel) => { const key = makeAddress(tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort); if (!mapHasAddressLocalhostOrAllInterfaces(this.forwarded, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort) <ins> && !mapHasAddressLocalhostOrAllInterfaces(this.detected, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort) </ins> && !mapHasAddressLocalhostOrAllInterfaces(this.inProgress, tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort) && tunnel.localAddress) { const matchingCandidate = mapHasAddressLocalhostOrAllInterfaces(this._candidates ?? new Map(), tunnel.tunnelRemoteHost, tunnel.tunnelRemotePort);