88*/
99
1010const http = require ( 'http' ) ;
11+ const https = require ( 'https' ) ;
1112const fs = require ( 'fs' ) ;
1213const os = require ( 'os' ) ;
1314
2122 // continue
2223}
2324
25+ let uriScheme = 'vscode' ;
26+ try {
27+ const schemeArg = process . argv . slice ( 2 ) [ 0 ] ;
28+ if ( schemeArg ) {
29+ uriScheme = schemeArg ;
30+ }
31+ } catch ( error ) {
32+ // continue
33+ }
34+
2435const server = http . createServer ( ( req , res ) => {
2536 if ( req . url === '/' ) {
2637 res . statusCode = 200 ;
@@ -52,6 +63,7 @@ const server = http.createServer((req, res) => {
5263 let keyMessage = hasUserPrefSSHKey ? userPubKey : genKey ;
5364 let encodedKeyMessage = Buffer . from ( hasUserPrefSSHKey ? userKey : genKey ) . toString ( 'base64url' ) ;
5465 let encodedUrl = encodeURIComponent ( process . env [ "CHE_DASHBOARD_URL" ] ) ;
66+ getHostURL ( ( hostURL ) => {
5567
5668 res . end ( `
5769<!DOCTYPE html>
@@ -87,8 +99,8 @@ const server = http.createServer((req, res) => {
8799 <li class="extension-li">Click the URI below (you may need to accept the prompt allowing this page to open the link with your VS Code-based editor) <b>OR</b> from the "Remote Explorer" view, select the <code>Connect to Dev Spaces</code> command and input the URI below.</li>
88100 <div class="parent">
89101 <div>
90- <a href="vscode ://redhat.devspaces-remote-ssh?namespace=${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } &podName=${ process . env [ "HOSTNAME" ] } &userName=${ username } &dwName=${ process . env [ "DEVWORKSPACE_NAME" ] } &key=${ encodedKeyMessage } &url=${ encodedUrl } ">
91- <pre id="uri-connection">vscode ://redhat.devspaces-remote-ssh?namespace=${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } &podName=${ process . env [ "HOSTNAME" ] } &userName=${ username } &dwName=${ process . env [ "DEVWORKSPACE_NAME" ] } &key=${ encodedKeyMessage } &url=${ encodedUrl } </pre>
102+ <a href="${ uriScheme } ://redhat.devspaces-remote-ssh?namespace=${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } &podName=${ process . env [ "HOSTNAME" ] } &userName=${ username } &dwName=${ process . env [ "DEVWORKSPACE_NAME" ] } &key=${ encodedKeyMessage } &url=${ encodedUrl } ">
103+ <pre id="uri-connection">${ uriScheme } ://redhat.devspaces-remote-ssh?namespace=${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } &podName=${ process . env [ "HOSTNAME" ] } &userName=${ username } &dwName=${ process . env [ "DEVWORKSPACE_NAME" ] } &key=${ encodedKeyMessage } &url=${ encodedUrl } </pre>
92104 </a>
93105 </div>
94106 <div class="clipboard">
@@ -104,7 +116,7 @@ const server = http.createServer((req, res) => {
104116 </div>
105117 <div id="docs-manual" hidden>
106118 <ol>
107- <li>Make sure your local <a href="${ process . env [ "CLUSTER_CONSOLE_URL" ] } /command-line-tools">oc client</a> is <a href="https://oauth-openshift ${ getHostURL ( ) } /oauth/token/request">logged in</a> to your OpenShift cluster</li>
119+ <li>Make sure your local <a href="${ process . env [ "CLUSTER_CONSOLE_URL" ] } /command-line-tools">oc client</a> is <a href="${ hostURL } /oauth/token/request">logged in</a> to your OpenShift cluster</li>
108120 <li><p class="center">Run <code id="port-forward">oc port-forward -n ${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } ${ process . env [ "HOSTNAME" ] } 2022:2022</code><a href="#"><svg class="clipboard-img-code" onclick="copyToClipboard('port-forward')" title="Copy" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 20 20">
109121 <path fill="currentColor" d="M12 0H2C.9 0 0 .9 0 2v10h1V2c0-.6.4-1 1-1h10V0z"></path>
110122 <path fill="currentColor" d="M18 20H8c-1.1 0-2-.9-2-2V8c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2v10c0 1.1-.9 2-2 2zM8 7c-.6 0-1 .4-1 1v10c0 .6.4 1 1 1h10c.6 0 1-.4 1-1V8c0-.6-.4-1-1-1H8z"></path>
@@ -159,11 +171,13 @@ const server = http.createServer((req, res) => {
159171 </div>
160172 <script>
161173 initializePlatformContent();
162- openDevspacesURI("${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } ", "${ process . env [ "HOSTNAME" ] } ", "${ username } ", "${ process . env [ "DEVWORKSPACE_NAME" ] } ", "${ encodedKeyMessage } ", "${ encodedUrl } ");
174+ openDevspacesURI("${ uriScheme } ", " ${ process . env [ "DEVWORKSPACE_NAMESPACE" ] } ", "${ process . env [ "HOSTNAME" ] } ", "${ username } ", "${ process . env [ "DEVWORKSPACE_NAME" ] } ", "${ encodedKeyMessage } ", "${ encodedUrl } ");
163175 </script>
164176 </body>
165177</html>
166178 ` ) ;
179+
180+ } ) ;
167181 } else {
168182 let loc = req . url . substring ( 1 ) ;
169183 let isBinaryData = false ;
@@ -197,16 +211,51 @@ server.listen(port, hostname, () => {
197211 console . log ( `Server running at http://${ hostname } :${ port } /` ) ;
198212} ) ;
199213
200- function getHostURL ( ) {
214+ function getHostURL ( callback ) {
215+
201216 const consoleURL = process . env [ "CLUSTER_CONSOLE_URL" ] ;
202217 const devspacesURL = process . env [ "CHE_DASHBOARD_URL" ] ;
218+
203219 if ( consoleURL === undefined || devspacesURL === undefined ) {
204- return undefined ;
220+ return callback ( undefined ) ;
205221 }
206- let i = 0 ;
207- while ( i < consoleURL . length && i < devspacesURL . length
208- && consoleURL . substring ( consoleURL . length - 1 - i ) === devspacesURL . substring ( devspacesURL . length - 1 - i ) ) {
209- i ++ ;
210- }
211- return consoleURL . substring ( consoleURL . length - i ) ;
222+
223+ console . log ( `Discovering cluster API URL via ${ devspacesURL } ` ) ;
224+ const host = new URL ( devspacesURL ) ;
225+ const oauthStartURL = `${ host . protocol } //${ host . host } /oauth/start` ;
226+
227+ const getFallbackURL = ( ) => {
228+ console . log ( 'Falling back to legacy discovery method.' ) ;
229+ let i = 0 ;
230+ while ( i < consoleURL . length && i < devspacesURL . length
231+ && consoleURL . substring ( consoleURL . length - 1 - i ) === devspacesURL . substring ( devspacesURL . length - 1 - i ) ) {
232+ i ++ ;
233+ }
234+ return `https://oauth-openshift${ consoleURL . substring ( consoleURL . length - i ) } ` ;
235+ } ;
236+
237+ // Follow the /oauth/start redirect to discover the real cluster hostname
238+ const mod = host . protocol === "https:" ? https : http ;
239+ const req = mod . get ( oauthStartURL , { rejectUnauthorized : false } , ( res ) => {
240+ clearTimeout ( timer ) ;
241+ res . resume ( ) ; // only interested in headers, so consume body
242+ if ( res . statusCode === 302 && res . headers . location ) {
243+ const resHost = new URL ( res . headers . location ) ;
244+ const resURL = `${ resHost . protocol } //${ resHost . host } ` ;
245+ console . log ( `Resolved API URL: ${ resURL } ` ) ;
246+ callback ( resURL ) ;
247+ } else {
248+ callback ( getFallbackURL ( ) ) ;
249+ }
250+ } ) ;
251+
252+ const timer = setTimeout ( ( ) => {
253+ req . destroy ( ) ;
254+ callback ( getFallbackURL ( ) ) ;
255+ } , 10000 ) ;
256+
257+ req . on ( 'error' , ( ) => {
258+ clearTimeout ( timer ) ;
259+ callback ( getFallbackURL ( ) ) ;
260+ } ) ;
212261}
0 commit comments