Skip to content

Commit 1b84a5e

Browse files
committed
Rework interface of unix_socket option
1 parent 3fb8606 commit 1b84a5e

File tree

3 files changed

+175
-130
lines changed

3 files changed

+175
-130
lines changed

docs/source/server-process.rst

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,16 @@ pairs.
103103
``unix_socket``
104104
^^^^^^^^^^^^^^^
105105

106-
If *True*, the server will listen on a Unix socket at a filesystem path, instead
107-
of a TCP port. The ``{port}`` argument (see :ref:`server-process-cmd`) will be a
108-
filesystem path for this socket instead of a port number. The server should
109-
create a Unix socket bound to this path and listen for HTTP requests on it.
110-
111-
The Unix socket will only be available to the user the server belongs to,
112-
whereas TCP sockets are available to any users on the same host.
113-
114-
If this is used, the ``port`` configuration key is ignored.
106+
This option uses a Unix socket on a filesystem path, instead of a TCP
107+
port. It can be passed as a string specifying the socket path, or *True* for
108+
Jupyter Server Proxy to create a temporary directory to hold the socket,
109+
ensuring that only the user running Jupyter can connect to it.
110+
111+
If this is used, the ``{port}`` argument in the command template
112+
(see :ref:`server-process-cmd`) will be a filesystem path for this socket
113+
instead of a port number. The server should create a Unix socket bound to
114+
this path and listen for HTTP requests on it. The ``port`` configuration key
115+
will be ignored.
115116

116117
Defaults to *False*.
117118

jupyter_server_proxy/config.py

Lines changed: 52 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
from traitlets.config import Configurable
77
from tornado import httpclient
88
from warnings import warn
9-
from .handlers import SuperviseAndProxyHandler, AddSlashHandler, RewritableResponse
9+
from .handlers import (
10+
NamedLocalProxyHandler, SuperviseAndProxyHandler, AddSlashHandler,
11+
)
1012
import pkg_resources
1113
from collections import namedtuple
1214
from .utils import call_with_asked_args
@@ -17,63 +19,56 @@
1719
except ImportError:
1820
from .utils import Callable
1921

20-
def _make_serverproxy_handler(name, command, environment, timeout, absolute_url, port, unix_socket, mappath, request_headers_override, rewrite_response):
22+
23+
LauncherEntry = namedtuple('LauncherEntry', ['enabled', 'icon_path', 'title', 'path_info'])
24+
ServerProcess = namedtuple('ServerProcess', [
25+
'name', 'command', 'environment', 'timeout', 'absolute_url', 'port', 'unix_socket',
26+
'mappath', 'launcher_entry', 'new_browser_tab', 'request_headers_override', 'rewrite_response',
27+
])
28+
29+
30+
def _make_namedproxy_handler(sp: ServerProcess):
31+
class _Proxy(NamedLocalProxyHandler):
32+
def __init__(self, *args, **kwargs):
33+
super().__init__(*args, **kwargs)
34+
self.name = sp.name
35+
self.proxy_base = sp.name
36+
self.absolute_url = sp.absolute_url
37+
self.port = sp.port
38+
self.unix_socket = sp.unix_socket
39+
self.mappath = sp.mappath
40+
self.rewrite_response = sp.rewrite_response
41+
42+
def get_request_headers_override(self):
43+
return self._realize_rendered_template(sp.request_headers_override)
44+
45+
return _Proxy
46+
47+
def _make_supervisedproxy_handler(sp: ServerProcess):
2148
"""
2249
Create a SuperviseAndProxyHandler subclass with given parameters
2350
"""
2451
# FIXME: Set 'name' properly
2552
class _Proxy(SuperviseAndProxyHandler):
2653
def __init__(self, *args, **kwargs):
2754
super().__init__(*args, **kwargs)
28-
self.name = name
29-
self.command = command
30-
self.proxy_base = name
31-
self.absolute_url = absolute_url
32-
self.requested_port = port
33-
self.unix_socket = unix_socket
34-
self.mappath = mappath
35-
self.rewrite_response = rewrite_response
36-
37-
@property
38-
def process_args(self):
39-
return {
40-
'port': self.port,
41-
'base_url': self.base_url,
42-
}
43-
44-
def _render_template(self, value):
45-
args = self.process_args
46-
if type(value) is str:
47-
return value.format(**args)
48-
elif type(value) is list:
49-
return [self._render_template(v) for v in value]
50-
elif type(value) is dict:
51-
return {
52-
self._render_template(k): self._render_template(v)
53-
for k, v in value.items()
54-
}
55-
else:
56-
raise ValueError('Value of unrecognized type {}'.format(type(value)))
57-
58-
def _realize_rendered_template(self, attribute):
59-
'''Call any callables, then render any templated values.'''
60-
if callable(attribute):
61-
attribute = self._render_template(
62-
call_with_asked_args(attribute, self.process_args)
63-
)
64-
return self._render_template(attribute)
65-
66-
def get_cmd(self):
67-
return self._realize_rendered_template(self.command)
55+
self.name = sp.name
56+
self.command = sp.command
57+
self.proxy_base = sp.name
58+
self.absolute_url = sp.absolute_url
59+
self.requested_port = sp.port
60+
self.requested_unix_socket = sp.unix_socket
61+
self.mappath = sp.mappath
62+
self.rewrite_response = sp.rewrite_response
6863

6964
def get_env(self):
70-
return self._realize_rendered_template(environment)
65+
return self._realize_rendered_template(sp.environment)
7166

7267
def get_request_headers_override(self):
73-
return self._realize_rendered_template(request_headers_override)
68+
return self._realize_rendered_template(sp.request_headers_override)
7469

7570
def get_timeout(self):
76-
return timeout
71+
return sp.timeout
7772

7873
return _Proxy
7974

@@ -94,31 +89,25 @@ def make_handlers(base_url, server_processes):
9489
"""
9590
handlers = []
9691
for sp in server_processes:
97-
handler = _make_serverproxy_handler(
98-
sp.name,
99-
sp.command,
100-
sp.environment,
101-
sp.timeout,
102-
sp.absolute_url,
103-
sp.port,
104-
sp.unix_socket,
105-
sp.mappath,
106-
sp.request_headers_override,
107-
sp.rewrite_response,
108-
)
92+
if sp.command:
93+
handler = _make_supervisedproxy_handler(sp)
94+
kwargs = dict(state={})
95+
else:
96+
if not (sp.port or isinstance(sp.unix_socket, str)):
97+
warn(f"Server proxy {sp.name} does not have a command, port "
98+
f"number or unix_socket path. At least one of these is "
99+
f"required.")
100+
continue
101+
handler = _make_namedproxy_handler(sp)
102+
kwargs = {}
109103
handlers.append((
110-
ujoin(base_url, sp.name, r'(.*)'), handler, dict(state={}),
104+
ujoin(base_url, sp.name, r'(.*)'), handler, kwargs,
111105
))
112106
handlers.append((
113107
ujoin(base_url, sp.name), AddSlashHandler
114108
))
115109
return handlers
116110

117-
LauncherEntry = namedtuple('LauncherEntry', ['enabled', 'icon_path', 'title', 'path_info'])
118-
ServerProcess = namedtuple('ServerProcess', [
119-
'name', 'command', 'environment', 'timeout', 'absolute_url', 'port', 'unix_socket',
120-
'mappath', 'launcher_entry', 'new_browser_tab', 'request_headers_override', 'rewrite_response',
121-
])
122111

123112
def make_server_process(name, server_process_config, serverproxy_config):
124113
le = server_process_config.get('launcher_entry', {})

0 commit comments

Comments
 (0)