|
1 | 1 | import importlib.util |
2 | 2 | from urllib.parse import quote_plus |
3 | 3 | import json |
| 4 | +import sys |
4 | 5 |
|
5 | 6 | # Widget dependencies |
6 | 7 | import anywidget |
@@ -104,7 +105,8 @@ def get_base_url_and_port(port, next_port, proxy=False, base_url=None, host_name |
104 | 105 |
|
105 | 106 | if base_url is None: |
106 | 107 | if proxy: |
107 | | - if importlib.util.find_spec('jupyter_server_proxy') is None: |
| 108 | + is_in_workspaces = sys.executable.startswith('/hive') |
| 109 | + if importlib.util.find_spec('jupyter_server_proxy') is None and not is_in_workspaces: |
108 | 110 | raise ValueError( |
109 | 111 | "To use the widget through a proxy, jupyter-server-proxy must be installed.") |
110 | 112 | if host_name is None: |
@@ -161,37 +163,52 @@ def get_uid_str(uid): |
161 | 163 | const { createRoot } = await importWithMap("react-dom/client", importMap); |
162 | 164 |
|
163 | 165 | const e = React.createElement; |
164 | | -
|
| 166 | +const WORKSPACES_URL_KEYWORD = 'https://workspaces-pt' |
165 | 167 | const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; |
166 | | -
|
167 | 168 | // The jupyter server may be running through a proxy, |
168 | 169 | // which means that the client needs to prepend the part of the URL before /proxy/8000 such as |
169 | 170 | // https://hub.gke2.mybinder.org/user/vitessce-vitessce-python-swi31vcv/proxy/8000/A/0/cells |
| 171 | +// For workspaces: https://workspaces-pt.hubmapconsortium.org/passthrough/HOSTNAME/PORT/ADDITIONAL_PATH_INFO?QUERY_PARAMS=HELLO_WORLD |
170 | 172 | function prependBaseUrl(config, proxy, hasHostName) { |
171 | | - if(!proxy || hasHostName) { |
172 | | - return config; |
173 | | - } |
174 | | - const { origin } = new URL(window.location.href); |
175 | | - let baseUrl; |
176 | | - const jupyterLabConfigEl = document.getElementById('jupyter-config-data'); |
177 | | -
|
178 | | - if (jupyterLabConfigEl) { |
179 | | - // This is jupyter lab |
180 | | - baseUrl = JSON.parse(jupyterLabConfigEl.textContent || '').baseUrl; |
181 | | - } else { |
182 | | - // This is jupyter notebook |
183 | | - baseUrl = document.getElementsByTagName('body')[0].getAttribute('data-base-url'); |
184 | | - } |
185 | | - return { |
186 | | - ...config, |
187 | | - datasets: config.datasets.map(d => ({ |
188 | | - ...d, |
189 | | - files: d.files.map(f => ({ |
190 | | - ...f, |
191 | | - url: `${origin}${baseUrl}${f.url}`, |
192 | | - })), |
193 | | - })), |
194 | | - }; |
| 173 | + if (!proxy || hasHostName) { |
| 174 | + return config; |
| 175 | + } |
| 176 | + const { origin, pathname } = new URL(window.location.href); |
| 177 | + const isInWorkspaces = origin.startsWith(WORKSPACES_URL_KEYWORD); |
| 178 | +
|
| 179 | + const jupyterLabConfigEl = document.getElementById('jupyter-config-data'); |
| 180 | +
|
| 181 | + let baseUrl; |
| 182 | + if (isInWorkspaces) { |
| 183 | + const pathSegments = pathname.split('/'); |
| 184 | + const passthroughIndex = pathSegments.indexOf('passthrough'); |
| 185 | + if (passthroughIndex !== -1) { |
| 186 | + baseUrl = pathSegments.slice(0, passthroughIndex + 2).join('/'); |
| 187 | + } |
| 188 | + } else if (jupyterLabConfigEl) { |
| 189 | + // This is jupyter lab |
| 190 | + baseUrl = JSON.parse(jupyterLabConfigEl.textContent || '').baseUrl; |
| 191 | + } else { |
| 192 | + // This is jupyter notebook |
| 193 | + baseUrl = document.getElementsByTagName('body')[0].getAttribute('data-base-url'); |
| 194 | + } |
| 195 | + return { |
| 196 | + ...config, |
| 197 | + datasets: config.datasets.map(d => ({ |
| 198 | + ...d, |
| 199 | + files: d.files.map(f => { |
| 200 | + if (isInWorkspaces && f.url.startsWith('proxy')) { |
| 201 | + // When the user is in workspaces, we do not use jupyter_server_proxy. |
| 202 | + // Instead, the workspaces infrastructure has its own "passthrough" functionality. |
| 203 | + f.url = f.url.replace('proxy', ''); |
| 204 | + } |
| 205 | + return { |
| 206 | + ...f, |
| 207 | + url: `${origin}${baseUrl}${f.url}`, |
| 208 | + }; |
| 209 | + }), |
| 210 | + })), |
| 211 | + }; |
195 | 212 | } |
196 | 213 |
|
197 | 214 | async function render(view) { |
|
0 commit comments