Skip to content

Commit ac861b2

Browse files
committed
Improve port forwarding in JetBrains EAP IDEs
1 parent 5743b9f commit ac861b2

File tree

16 files changed

+313
-358
lines changed

16 files changed

+313
-358
lines changed

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodCLIService.kt

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.intellij.ide.BrowserUtil
99
import com.intellij.openapi.client.ClientSession
1010
import com.intellij.openapi.client.ClientSessionsManager
1111
import com.intellij.openapi.components.service
12+
import com.intellij.openapi.components.serviceOrNull
1213
import com.intellij.openapi.diagnostic.thisLogger
1314
import com.intellij.openapi.project.Project
1415
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
@@ -18,6 +19,7 @@ import com.intellij.util.withFragment
1819
import com.intellij.util.withPath
1920
import com.intellij.util.withQuery
2021
import com.jetbrains.rd.util.URI
22+
import io.gitpod.jetbrains.remote.utils.LocalHostUri
2123
import io.netty.buffer.Unpooled
2224
import io.netty.channel.ChannelHandlerContext
2325
import io.netty.handler.codec.http.FullHttpRequest
@@ -29,12 +31,12 @@ import org.jetbrains.io.response
2931
import java.io.OutputStreamWriter
3032
import java.nio.file.InvalidPathException
3133
import java.nio.file.Path
34+
import java.util.*
3235

3336
@Suppress("UnstableApiUsage", "OPT_IN_USAGE")
3437
class GitpodCLIService : RestService() {
3538

3639
private val manager = service<GitpodManager>()
37-
private val portsService = service<GitpodPortsService>()
3840
private val cliHelperService = service<GitpodCLIHelper>()
3941

4042
override fun getServiceName() = SERVICE_NAME
@@ -74,29 +76,35 @@ class GitpodCLIService : RestService() {
7476
return "url is missing"
7577
}
7678

77-
val resolvedUrl = resolveExternalUrl(url)
78-
7979
return withClient(request, context) { project ->
80+
var resolvedUrl = url
81+
val uri = URI.create(url)
82+
val localHostUriMetadata = LocalHostUri.extractLocalHostUriMetaDataForPortMapping(uri)
83+
val gitpodPortForwardingService = serviceOrNull<GitpodPortForwardingService>()
84+
85+
if (localHostUriMetadata.isPresent && gitpodPortForwardingService != null) {
86+
var localHostUriFromPort = Optional.empty<URI>()
87+
88+
application.invokeAndWait {
89+
localHostUriFromPort = gitpodPortForwardingService
90+
.getLocalHostUriFromHostPort(localHostUriMetadata.get().port)
91+
}
92+
93+
if (localHostUriFromPort.isPresent) {
94+
resolvedUrl = localHostUriFromPort.get()
95+
.withPath(uri.path)
96+
.withQuery(uri.query)
97+
.withFragment(uri.fragment)
98+
.toString()
99+
}
100+
}
101+
80102
BrowserUtil.browse(resolvedUrl, project)
81103
}
82104
}
83105
return "invalid operation"
84106
}
85107

86-
private fun resolveExternalUrl(url: String): String {
87-
val uri = URI.create(url)
88-
val optionalLocalHostUriMetadata = portsService.extractLocalHostUriMetaDataForPortMapping(uri)
89-
90-
return when {
91-
optionalLocalHostUriMetadata.isEmpty -> url
92-
else -> portsService.getLocalHostUriFromHostPort(optionalLocalHostUriMetadata.get().port)
93-
.withPath(uri.path)
94-
.withQuery(uri.query)
95-
.withFragment(uri.fragment)
96-
.toString()
97-
}
98-
}
99-
100108
private fun withClient(request: FullHttpRequest, context: ChannelHandlerContext, action: suspend (project: Project?) -> Unit): String? {
101109
GlobalScope.launch {
102110
getClientSessionAndProjectAsync().let { (session, project) ->

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodClientProjectSessionTracker.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.intellij.notification.NotificationType
1111
import com.intellij.openapi.Disposable
1212
import com.intellij.openapi.client.ClientSessionsManager
1313
import com.intellij.openapi.components.service
14+
import com.intellij.openapi.components.serviceOrNull
1415
import com.intellij.openapi.diagnostic.thisLogger
1516
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
1617
import com.intellij.openapi.fileEditor.FileEditorManagerListener
@@ -29,14 +30,14 @@ import io.grpc.stub.ClientCallStreamObserver
2930
import io.grpc.stub.ClientResponseObserver
3031
import kotlinx.coroutines.*
3132
import kotlinx.coroutines.future.await
33+
import java.util.*
3234
import java.util.concurrent.CancellationException
3335
import java.util.concurrent.CompletableFuture
3436

3537
@Suppress("UnstableApiUsage", "OPT_IN_USAGE")
3638
class GitpodClientProjectSessionTracker(private val project: Project) : Disposable {
3739

3840
private val manager = service<GitpodManager>()
39-
private val portsService = service<GitpodPortsService>()
4041
private val session = ClientSessionsManager.getProjectSession(project)
4142

4243
private lateinit var info: Info.WorkspaceInfoResponse
@@ -64,8 +65,12 @@ class GitpodClientProjectSessionTracker(private val project: Project) : Disposab
6465
}
6566

6667
private fun getForwardedPortUrl(port: PortsStatus): String {
68+
val localHostUri = serviceOrNull<GitpodPortForwardingService>()
69+
?.getLocalHostUriFromHostPort(port.localPort)
70+
?: Optional.empty()
71+
6772
return when {
68-
portsService.isForwarded(port.localPort) -> portsService.getLocalHostUriFromHostPort(port.localPort).toString()
73+
localHostUri.isPresent -> localHostUri.get().toString()
6974
else -> port.exposed.url
7075
}
7176
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package io.gitpod.jetbrains.remote
66

77
import com.intellij.openapi.Disposable
8+
import java.util.Optional
9+
import com.jetbrains.rd.util.URI
810

9-
interface GitpodGlobalPortForwardingService {
10-
fun monitorPortsOfPid(disposable: Disposable, pid: Long)
11+
interface GitpodPortForwardingService : Disposable {
12+
/** Returns the localhost URI if the given port is forwarded on client. */
13+
fun getLocalHostUriFromHostPort(hostPort: Int): Optional<URI>
1114
}

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodPortsService.kt

Lines changed: 0 additions & 81 deletions
This file was deleted.

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodTerminalService.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
package io.gitpod.jetbrains.remote
66

7-
// import com.intellij.openapi.components.service
87
import com.intellij.openapi.diagnostic.thisLogger
98
import com.intellij.openapi.project.Project
109
import com.intellij.util.application
@@ -35,7 +34,6 @@ class GitpodTerminalService(project: Project) {
3534
private val terminalServiceFutureStub = TerminalServiceGrpc.newFutureStub(GitpodManager.supervisorChannel)
3635
private val terminalServiceStub = TerminalServiceGrpc.newStub(GitpodManager.supervisorChannel)
3736
private val statusServiceStub = StatusServiceGrpc.newStub(GitpodManager.supervisorChannel)
38-
// private val portForwardingService = service<GitpodGlobalPortForwardingService>()
3937

4038
init {
4139
start()
@@ -187,10 +185,6 @@ class GitpodTerminalService(project: Project) {
187185
exitTaskWhenTerminalWidgetGetsClosed(supervisorTerminal, shellTerminalWidget)
188186

189187
listenForTaskTerminationAndTitleChanges(supervisorTerminal, shellTerminalWidget)
190-
191-
// This works for auto-forwarding ports opened in Gitpod Terminals, but it's currently not useful as we
192-
// have the GitpodPortForwardingService already auto-forwarding all the ports from the workspace.
193-
// portForwardingService.monitorPortsOfPid(shellTerminalWidget, supervisorTerminal.pid)
194188
}
195189

196190
private fun listenForTaskTerminationAndTitleChanges(

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodCopyUrlAction.kt

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,30 @@ import com.intellij.openapi.actionSystem.ActionPlaces
88
import com.intellij.openapi.actionSystem.ActionUpdateThread
99
import com.intellij.openapi.actionSystem.AnAction
1010
import com.intellij.openapi.actionSystem.AnActionEvent
11-
import com.intellij.openapi.components.service
1211
import com.intellij.openapi.ide.CopyPasteManager
12+
import com.jetbrains.rd.platform.codeWithMe.portForwarding.ClientPortState
13+
import com.jetbrains.rd.platform.codeWithMe.portForwarding.PortConfiguration
1314
import com.jetbrains.rd.platform.codeWithMe.portForwarding.PortForwardingDataKeys
14-
import io.gitpod.jetbrains.remote.GitpodPortsService
15+
import org.apache.http.client.utils.URIBuilder
1516
import java.awt.datatransfer.StringSelection
1617

1718
@Suppress("ComponentNotRegistered", "UnstableApiUsage")
1819
class GitpodCopyUrlAction : AnAction() {
1920
override fun actionPerformed(e: AnActionEvent) {
20-
e.dataContext.getData(PortForwardingDataKeys.SUGGESTION)?.getSuggestedHostPort()?.let { hostPort ->
21-
service<GitpodPortsService>().getLocalHostUriFromHostPort(hostPort).let { localHostUri ->
22-
CopyPasteManager.getInstance().setContents(StringSelection(localHostUri.toString()))
23-
}
24-
}
21+
(e.dataContext.getData(PortForwardingDataKeys.PORT)
22+
?.configuration as PortConfiguration.PerClientTcpForwarding?)
23+
?.clientPortState?.let {
24+
if (it is ClientPortState.Assigned) {
25+
CopyPasteManager.getInstance().setContents(StringSelection(
26+
URIBuilder()
27+
.setScheme("http")
28+
.setHost(it.clientInterface)
29+
.setPort(it.clientPort)
30+
.build()
31+
.toString())
32+
)
33+
}
34+
}
2535
}
2636

2737
override fun update(e: AnActionEvent) {

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodCopyWebUrlAction.kt

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,21 @@ import com.intellij.openapi.actionSystem.ActionPlaces
88
import com.intellij.openapi.actionSystem.ActionUpdateThread
99
import com.intellij.openapi.actionSystem.AnAction
1010
import com.intellij.openapi.actionSystem.AnActionEvent
11+
import com.intellij.openapi.components.service
1112
import com.intellij.openapi.ide.CopyPasteManager
12-
import com.intellij.util.application
13+
import com.jetbrains.rd.platform.codeWithMe.portForwarding.PerClientPortForwardingManager
14+
import com.jetbrains.rd.platform.codeWithMe.portForwarding.PortConfiguration
1315
import com.jetbrains.rd.platform.codeWithMe.portForwarding.PortForwardingDataKeys
14-
import io.gitpod.jetbrains.remote.GitpodManager
15-
import io.gitpod.supervisor.api.Status.PortsStatusRequest
16-
import io.gitpod.supervisor.api.StatusServiceGrpc
17-
import kotlinx.coroutines.launch
1816
import java.awt.datatransfer.StringSelection
1917

2018
@Suppress("ComponentNotRegistered", "UnstableApiUsage")
2119
class GitpodCopyWebUrlAction : AnAction() {
2220
override fun actionPerformed(e: AnActionEvent) {
2321
e.dataContext.getData(PortForwardingDataKeys.SUGGESTION)?.getSuggestedHostPort()?.let { hostPort ->
24-
application.coroutineScope.launch {
25-
getUrlFromPort(hostPort)?.let {
26-
CopyPasteManager.getInstance().setContents(StringSelection(it))
27-
}
22+
(service<PerClientPortForwardingManager>().getPorts(hostPort).firstOrNull {
23+
it.labels.contains(GitpodPortForwardingServiceImpl.EXPOSED_PORT_LABEL)
24+
}?.configuration as PortConfiguration.UrlExposure?)?.exposedUrl?.let {
25+
CopyPasteManager.getInstance().setContents(StringSelection(it))
2826
}
2927
}
3028
}
@@ -34,17 +32,4 @@ class GitpodCopyWebUrlAction : AnAction() {
3432
}
3533

3634
override fun getActionUpdateThread() = ActionUpdateThread.BGT
37-
38-
private fun getUrlFromPort(port: Number): String? {
39-
val blockingStub = StatusServiceGrpc.newBlockingStub(GitpodManager.supervisorChannel)
40-
val request = PortsStatusRequest.newBuilder().setObserve(false).build()
41-
val response = blockingStub.portsStatus(request)
42-
while (response.hasNext()) {
43-
val portStatusResponse = response.next()
44-
for (portStatus in portStatusResponse.portsList) {
45-
if (portStatus.localPort == port) return portStatus.exposed.url
46-
}
47-
}
48-
return null
49-
}
5035
}

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodGlobalPortForwardingServiceImpl.kt

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)