16
16
from traitlets .config import Configurable
17
17
18
18
from .handlers import AddSlashHandler , NamedLocalProxyHandler , SuperviseAndProxyHandler
19
+ from .rawsocket import RawSocketHandler , SuperviseAndRawSocketHandler
19
20
20
21
try :
21
22
# Traitlets >= 4.3.3
43
44
"request_headers_override" ,
44
45
"rewrite_response" ,
45
46
"update_last_activity" ,
47
+ "raw_socket_proxy" ,
46
48
],
47
49
)
48
50
49
51
50
- def _make_namedproxy_handler (sp : ServerProcess ):
51
- class _Proxy (NamedLocalProxyHandler ):
52
- def __init__ (self , * args , ** kwargs ):
53
- super ().__init__ (* args , ** kwargs )
54
- self .name = sp .name
55
- self .proxy_base = sp .name
56
- self .absolute_url = sp .absolute_url
57
- self .port = sp .port
58
- self .unix_socket = sp .unix_socket
59
- self .mappath = sp .mappath
60
- self .rewrite_response = sp .rewrite_response
61
- self .update_last_activity = sp .update_last_activity
62
-
63
- def get_request_headers_override (self ):
64
- return self ._realize_rendered_template (sp .request_headers_override )
65
-
66
- return _Proxy
67
-
68
-
69
- def _make_supervisedproxy_handler (sp : ServerProcess ):
52
+ def _make_proxy_handler (sp : ServerProcess ):
70
53
"""
71
- Create a SuperviseAndProxyHandler subclass with given parameters
54
+ Create an appropriate handler with given parameters
72
55
"""
56
+ if sp .command :
57
+ cls = SuperviseAndRawSocketHandler if sp .raw_socket_proxy else SuperviseAndProxyHandler
58
+ args = dict (state = {})
59
+ elif not (sp .port or isinstance (sp .unix_socket , str )):
60
+ warn (
61
+ f"Server proxy { sp .name } does not have a command, port "
62
+ f"number or unix_socket path. At least one of these is "
63
+ f"required."
64
+ )
65
+ return
66
+ else :
67
+ cls = RawSocketHandler if sp .raw_socket_proxy else NamedLocalProxyHandler
68
+ args = {}
73
69
74
70
# FIXME: Set 'name' properly
75
- class _Proxy (SuperviseAndProxyHandler ):
71
+ class _Proxy (cls ):
72
+ kwargs = args
73
+
76
74
def __init__ (self , * args , ** kwargs ):
77
75
super ().__init__ (* args , ** kwargs )
78
76
self .name = sp .name
79
77
self .command = sp .command
80
78
self .proxy_base = sp .name
81
79
self .absolute_url = sp .absolute_url
82
- self .requested_port = sp .port
83
- self .requested_unix_socket = sp .unix_socket
80
+ if sp .command :
81
+ self .requested_port = sp .port
82
+ self .requested_unix_socket = sp .unix_socket
83
+ else :
84
+ self .port = sp .port
85
+ self .unix_socket = sp .unix_socket
84
86
self .mappath = sp .mappath
85
87
self .rewrite_response = sp .rewrite_response
86
88
self .update_last_activity = sp .update_last_activity
87
89
88
- def get_env (self ):
89
- return self ._realize_rendered_template (sp .environment )
90
-
91
90
def get_request_headers_override (self ):
92
91
return self ._realize_rendered_template (sp .request_headers_override )
93
92
93
+ # these two methods are only used in supervise classes, but do no harm otherwise
94
+ def get_env (self ):
95
+ return self ._realize_rendered_template (sp .environment )
96
+
94
97
def get_timeout (self ):
95
98
return sp .timeout
96
99
@@ -116,24 +119,14 @@ def make_handlers(base_url, server_processes):
116
119
"""
117
120
handlers = []
118
121
for sp in server_processes :
119
- if sp .command :
120
- handler = _make_supervisedproxy_handler (sp )
121
- kwargs = dict (state = {})
122
- else :
123
- if not (sp .port or isinstance (sp .unix_socket , str )):
124
- warn (
125
- f"Server proxy { sp .name } does not have a command, port "
126
- f"number or unix_socket path. At least one of these is "
127
- f"required."
128
- )
129
- continue
130
- handler = _make_namedproxy_handler (sp )
131
- kwargs = {}
122
+ handler = _make_proxy_handler (sp )
123
+ if not handler :
124
+ continue
132
125
handlers .append (
133
126
(
134
127
ujoin (base_url , sp .name , r"(.*)" ),
135
128
handler ,
136
- kwargs ,
129
+ handler . kwargs
137
130
)
138
131
)
139
132
handlers .append ((ujoin (base_url , sp .name ), AddSlashHandler ))
@@ -169,6 +162,7 @@ def make_server_process(name, server_process_config, serverproxy_config):
169
162
update_last_activity = server_process_config .get (
170
163
"update_last_activity" , True
171
164
),
165
+ raw_socket_proxy = server_process_config .get ("raw_socket_proxy" , False ),
172
166
)
173
167
174
168
@@ -292,6 +286,12 @@ def cats_only(response, path):
292
286
293
287
update_last_activity
294
288
Will cause the proxy to report activity back to jupyter server.
289
+
290
+ raw_socket_proxy
291
+ Proxy websocket requests as a raw TCP (or unix socket) stream.
292
+ In this mode, only websockets are handled, and messages are sent to the backend,
293
+ similar to running a websockify layer (https://github.com/novnc/websockify).
294
+ All other HTTP requests return 405 (and thus this will also bypass rewrite_response).
295
295
""" ,
296
296
config = True ,
297
297
)
0 commit comments