-
Notifications
You must be signed in to change notification settings - Fork 434
Expand file tree
/
Copy pathpreviewurl.ts
More file actions
122 lines (112 loc) · 3.29 KB
/
previewurl.ts
File metadata and controls
122 lines (112 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
* previewurl.ts
*
* Copyright (C) 2020-2023 Posit Software, PBC
*/
import { info } from "../deno_ral/log.ts";
import * as colors from "fmt/colors";
import {
isJupyterHubServer,
isJupyterServer,
isPositWorkbench,
isRStudioServer,
isVSCodeServer,
isVSCodeTerminal,
jupyterHubHttpReferrer,
jupyterHubUser,
vsCodeServerProxyUri,
} from "./platform.ts";
import { execProcess } from "./process.ts";
import { kLocalhost } from "./port-consts.ts";
import { findOpenPort, waitForPort } from "./port.ts";
export interface HostAndPortOptions {
port?: number;
host?: string;
}
export async function resolveHostAndPort(
options: HostAndPortOptions,
): Promise<{ host: string; port: number }> {
const host = options.host || kLocalhost;
let port = options.port;
// if a specific port is requested then wait for it up to 5 seconds
if (port) {
if (!await waitForPort({ port: port, hostname: host })) {
throw new Error(`Requested port ${options.port} is already in use.`);
}
} else {
port = findOpenPort();
}
return { host, port };
}
export function previewURL(host: string, port: number, path: string) {
// render 127.0.0.1 as localhost as not to break existing unit tests (see #947)
const showHost = host == "127.0.0.1" ? "localhost" : host;
const url = `http://${showHost}:${port}/${path}`;
return url;
}
export async function printBrowsePreviewMessage(
host: string,
port: number,
path: string,
) {
if (
(isJupyterServer() || isVSCodeTerminal()) && isPositWorkbench()
) {
const url = await rswURL(port, path);
info(`\nPreview server: ${previewURL(host, port, path = "")}`);
info(`\nBrowse at ${url}`, { format: colors.green });
} else if (isVSCodeTerminal() && isVSCodeServer()) {
const proxyUrl = vsCodeServerProxyUri()!;
if (proxyUrl.endsWith("/")) {
path = path.startsWith("/") ? path.slice(1) : path;
} else {
path = path.startsWith("/") ? path : "/" + path;
}
const browseUrl = proxyUrl.replace("{{port}}", `${port}`) +
path;
info(`\nBrowse at ${browseUrl}`, { format: colors.green });
} else if (isJupyterHubServer()) {
const httpReferrer = `${
jupyterHubHttpReferrer() || "<jupyterhub-server-url>/"
}user/${jupyterHubUser()}/`;
info(
`\nBrowse at ${httpReferrer}proxy/${port}/${path}`,
{
format: colors.green,
},
);
} else {
const url = previewURL(host, port, path);
if (!isRStudioServer()) {
info(`Browse at `, {
newline: false,
format: colors.green,
});
}
info(url, { format: (str: string) => colors.underline(colors.green(str)) });
}
}
export async function rswURL(port: number, path: string) {
const server = Deno.env.get("RS_SERVER_URL")!;
const session = Deno.env.get("RS_SESSION_URL")!;
const portToken = await rswPortToken(port);
const url = `${server}${session.slice(1)}p/${portToken}/${path}`;
return url;
}
async function rswPortToken(port: number) {
const result = await execProcess(
{
cmd: "/usr/lib/rstudio-server/bin/rserver-url",
args: [String(port)],
stdout: "piped",
stderr: "piped",
},
);
if (result.success) {
return result.stdout;
} else {
throw new Error(
`Failed to map RSW port token (status ${result.code})\n${result.stderr}`,
);
}
}