Skip to content

Commit 49dcbb6

Browse files
committed
Improve port forwarding in JetBrains EAP IDEs
1 parent 6dfd3f7 commit 49dcbb6

17 files changed

+329
-358
lines changed

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

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import com.intellij.util.withFragment
1818
import com.intellij.util.withPath
1919
import com.intellij.util.withQuery
2020
import com.jetbrains.rd.util.URI
21+
import io.gitpod.jetbrains.remote.utils.LocalHostUri
2122
import io.netty.buffer.Unpooled
2223
import io.netty.channel.ChannelHandlerContext
2324
import io.netty.handler.codec.http.FullHttpRequest
@@ -29,12 +30,12 @@ import org.jetbrains.io.response
2930
import java.io.OutputStreamWriter
3031
import java.nio.file.InvalidPathException
3132
import java.nio.file.Path
33+
import java.util.*
3234

3335
@Suppress("UnstableApiUsage", "OPT_IN_USAGE")
3436
class GitpodCLIService : RestService() {
3537

3638
private val manager = service<GitpodManager>()
37-
private val portsService = service<GitpodPortsService>()
3839
private val cliHelperService = service<GitpodCLIHelper>()
3940

4041
override fun getServiceName() = SERVICE_NAME
@@ -74,29 +75,35 @@ class GitpodCLIService : RestService() {
7475
return "url is missing"
7576
}
7677

77-
val resolvedUrl = resolveExternalUrl(url)
78-
7978
return withClient(request, context) { project ->
79+
var resolvedUrl = url
80+
val uri = URI.create(url)
81+
val localHostUriMetadata = LocalHostUri.extractLocalHostUriMetaDataForPortMapping(uri)
82+
83+
if (localHostUriMetadata.isPresent) {
84+
val gitpodPortForwardingService = service<GitpodPortForwardingService>()
85+
var localHostUriFromPort = Optional.empty<URI>()
86+
87+
application.invokeAndWait {
88+
localHostUriFromPort = gitpodPortForwardingService
89+
.getLocalHostUriFromHostPort(localHostUriMetadata.get().port)
90+
}
91+
92+
if (localHostUriFromPort.isPresent) {
93+
resolvedUrl = localHostUriFromPort.get()
94+
.withPath(uri.path)
95+
.withQuery(uri.query)
96+
.withFragment(uri.fragment)
97+
.toString()
98+
}
99+
}
100+
80101
BrowserUtil.browse(resolvedUrl, project)
81102
}
82103
}
83104
return "invalid operation"
84105
}
85106

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-
100107
private fun withClient(request: FullHttpRequest, context: ChannelHandlerContext, action: suspend (project: Project?) -> Unit): String? {
101108
GlobalScope.launch {
102109
getClientSessionAndProjectAsync().let { (session, project) ->

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import java.util.concurrent.CompletableFuture
3636
class GitpodClientProjectSessionTracker(private val project: Project) : Disposable {
3737

3838
private val manager = service<GitpodManager>()
39-
private val portsService = service<GitpodPortsService>()
39+
private val gitpodPortForwardingService = service<GitpodPortForwardingService>()
4040
private val session = ClientSessionsManager.getProjectSession(project)
4141

4242
private lateinit var info: Info.WorkspaceInfoResponse
@@ -64,8 +64,9 @@ class GitpodClientProjectSessionTracker(private val project: Project) : Disposab
6464
}
6565

6666
private fun getForwardedPortUrl(port: PortsStatus): String {
67+
val localHostUri = gitpodPortForwardingService.getLocalHostUriFromHostPort(port.localPort)
6768
return when {
68-
portsService.isForwarded(port.localPort) -> portsService.getLocalHostUriFromHostPort(port.localPort).toString()
69+
localHostUri.isPresent -> localHostUri.get().toString()
6970
else -> port.exposed.url
7071
}
7172
}
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)