Skip to content

Commit 831fe1f

Browse files
committed
Switch back to using entrypoints to serve desktop-websocket
This is simpler than inheriting from the proxying handler from jupyter_server_proxy directly, and more importantly keeps our launcher entry simple and existing!
1 parent a1d2280 commit 831fe1f

File tree

5 files changed

+82
-67
lines changed

5 files changed

+82
-67
lines changed

js/index.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ function status(text) {
3030
document.getElementById("status").textContent = text;
3131
}
3232

33-
// The websockify URL to connect to is the same URL we are rendering this page on!
34-
let websockifyUrl = new URL(window.location);
33+
// This page is served under the /desktop/, and the websockify websocket is served
34+
// under /desktop-websockify/ with the same base url as /desktop/. We resolve it relatively
35+
// this way.
36+
let websockifyUrl = new URL("../desktop-websockify/", window.location);
3537
websockifyUrl.protocol = window.location.protocol === "https:" ? "wss" : "ws";
3638

3739
// Creating a new RFB object will start a new connection

jupyter_remote_desktop_proxy/handlers.py

+3-63
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import os
2-
import shlex
3-
import tempfile
4-
from shutil import which
52

63
import jinja2
7-
from jupyter_server_proxy.handlers import SuperviseAndProxyHandler
4+
from jupyter_server.base.handlers import JupyterHandler
85
from tornado import web
96

107
jinja_env = jinja2.Environment(
@@ -17,66 +14,9 @@
1714
HERE = os.path.dirname(os.path.abspath(__file__))
1815

1916

20-
def get_websockify_command():
21-
# make a secure temporary directory for sockets
22-
# This is only readable, writeable & searchable by our uid
23-
sockets_dir = tempfile.mkdtemp()
24-
sockets_path = os.path.join(sockets_dir, 'vnc-socket')
25-
vncserver = which('vncserver')
26-
27-
if vncserver is None:
28-
# Use bundled tigervnc
29-
vncserver = os.path.join(HERE, 'share/tigervnc/bin/vncserver')
30-
31-
# TigerVNC provides the option to connect a Unix socket. TurboVNC does not.
32-
# TurboVNC and TigerVNC share the same origin and both use a Perl script
33-
# as the executable vncserver. We can determine if vncserver is TigerVNC
34-
# by searching TigerVNC string in the Perl script.
35-
with open(vncserver) as vncserver_file:
36-
is_tigervnc = "TigerVNC" in vncserver_file.read()
37-
38-
if is_tigervnc:
39-
vnc_args = [vncserver, '-rfbunixpath', sockets_path]
40-
socket_args = ['--unix-target', sockets_path]
41-
else:
42-
vnc_args = [vncserver]
43-
socket_args = []
44-
45-
if not os.path.exists(os.path.expanduser('~/.vnc/xstartup')):
46-
vnc_args.extend(['-xstartup', os.path.join(HERE, 'share/xstartup')])
47-
48-
vnc_command = shlex.join(
49-
vnc_args
50-
+ [
51-
'-verbose',
52-
'-geometry',
53-
'1680x1050',
54-
'-SecurityTypes',
55-
'None',
56-
'-fg',
57-
]
58-
)
59-
60-
return (
61-
[
62-
'websockify',
63-
'-v',
64-
'--heartbeat',
65-
'30',
66-
'{port}',
67-
]
68-
+ socket_args
69-
+ ['--', '/bin/sh', '-c', f'cd {os.getcwd()} && {vnc_command}']
70-
)
71-
72-
73-
class DesktopHandler(SuperviseAndProxyHandler):
74-
def __init__(self, *args, **kwargs):
75-
super().__init__(*args, **kwargs)
76-
self.command = get_websockify_command()
77-
17+
class DesktopHandler(JupyterHandler):
7818
@web.authenticated
79-
async def http_get(self, *args, **kwargs):
19+
async def get(self):
8020
template_params = {
8121
'base_url': self.base_url,
8222
}

jupyter_remote_desktop_proxy/server_extension.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ def load_jupyter_server_extension(server_app):
1818
server_app.web_app.add_handlers(
1919
".*",
2020
[
21+
# Serve our own static files
2122
(
2223
url_path_join(base_url, "/desktop/static/(.*)"),
2324
AuthenticatedFileHandler,
2425
{"path": (str(HERE / "static"))},
2526
),
27+
# To simplify URL mapping, we make sure that /desktop/ always
28+
# has a trailing slash
2629
(url_path_join(base_url, "/desktop"), AddSlashHandler),
27-
(url_path_join(base_url, "/desktop/()"), DesktopHandler, {'state': {}}),
30+
(url_path_join(base_url, "/desktop/"), DesktopHandler),
2831
],
2932
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import os
2+
import shlex
3+
import tempfile
4+
from shutil import which
5+
6+
HERE = os.path.dirname(os.path.abspath(__file__))
7+
8+
9+
def setup_websockify():
10+
# make a secure temporary directory for sockets
11+
# This is only readable, writeable & searchable by our uid
12+
sockets_dir = tempfile.mkdtemp()
13+
sockets_path = os.path.join(sockets_dir, 'vnc-socket')
14+
vncserver = which('vncserver')
15+
16+
if vncserver is None:
17+
# Use bundled tigervnc
18+
vncserver = os.path.join(HERE, 'share/tigervnc/bin/vncserver')
19+
20+
# TigerVNC provides the option to connect a Unix socket. TurboVNC does not.
21+
# TurboVNC and TigerVNC share the same origin and both use a Perl script
22+
# as the executable vncserver. We can determine if vncserver is TigerVNC
23+
# by searching TigerVNC string in the Perl script.
24+
with open(vncserver) as vncserver_file:
25+
is_tigervnc = "TigerVNC" in vncserver_file.read()
26+
27+
if is_tigervnc:
28+
vnc_args = [vncserver, '-rfbunixpath', sockets_path]
29+
socket_args = ['--unix-target', sockets_path]
30+
else:
31+
vnc_args = [vncserver]
32+
socket_args = []
33+
34+
if not os.path.exists(os.path.expanduser('~/.vnc/xstartup')):
35+
vnc_args.extend(['-xstartup', os.path.join(HERE, 'share/xstartup')])
36+
37+
vnc_command = shlex.join(
38+
vnc_args
39+
+ [
40+
'-verbose',
41+
'-geometry',
42+
'1680x1050',
43+
'-SecurityTypes',
44+
'None',
45+
'-fg',
46+
]
47+
)
48+
49+
return {
50+
'command': [
51+
'websockify',
52+
'-v',
53+
'--heartbeat',
54+
'30',
55+
'{port}',
56+
]
57+
+ socket_args
58+
+ ['--', '/bin/sh', '-c', f'cd {os.getcwd()} && {vnc_command}'],
59+
'timeout': 30,
60+
'new_browser_window': True,
61+
# We want the launcher entry to point to /desktop/, not to /desktop-websockify/
62+
# /desktop/ is the user facing URL, while /desktop-websockify/ now *only* serves
63+
# websockets.
64+
"launcher_entry": {"title": "Desktop", "path_info": "desktop"},
65+
}

setup.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ def run(self):
5858
"Programming Language :: Python :: 3",
5959
],
6060
description="Run a desktop environments on Jupyter",
61-
install_requires=[
61+
entry_points={
62+
'jupyter_serverproxy_servers': [
63+
'desktop-websockify = jupyter_remote_desktop_proxy.setup_websockify:setup_websockify',
64+
]
65+
},
66+
stall_requires=[
6267
'jupyter-server-proxy>=1.4.0',
6368
],
6469
include_package_data=True,

0 commit comments

Comments
 (0)