Skip to content

Commit b3867ca

Browse files
committed
Update url modification function
1 parent da22eef commit b3867ca

File tree

1 file changed

+28
-31
lines changed

1 file changed

+28
-31
lines changed

src/vitessce/widget.py

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import importlib.util
22
from urllib.parse import quote_plus
33
import json
4+
import sys
45

56
# Widget dependencies
67
import anywidget
@@ -104,7 +105,8 @@ def get_base_url_and_port(port, next_port, proxy=False, base_url=None, host_name
104105

105106
if base_url is None:
106107
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:
108110
raise ValueError(
109111
"To use the widget through a proxy, jupyter-server-proxy must be installed.")
110112
if host_name is None:
@@ -167,23 +169,24 @@ def get_uid_str(uid):
167169
// which means that the client needs to prepend the part of the URL before /proxy/8000 such as
168170
// https://hub.gke2.mybinder.org/user/vitessce-vitessce-python-swi31vcv/proxy/8000/A/0/cells
169171
// For workspaces: https://workspaces-pt.hubmapconsortium.org/passthrough/HOSTNAME/PORT/ADDITIONAL_PATH_INFO?QUERY_PARAMS=HELLO_WORLD
170-
function prependBaseUrl(config, proxy, hasHostName) {
171-
if (!proxy || hasHostName) {
172-
return config;
173-
}
174-
let proxyPath;
175-
const { origin } = new URL(window.location.href);
176-
const isInWorkspaces = origin.includes(WORKSPACES_URL_KEYWORD)
172+
function prependBaseUrl(config, proxy, hasHostName, currentPort) {
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 localhostBaseUrl = `http://localhost:${currentPort}`;
180+
const jupyterLabConfigEl = document.getElementById('jupyter-config-data');
181+
182+
let baseUrl;
177183
if (isInWorkspaces) {
178-
const pathSegments = window.location.pathname.split('/');
184+
const pathSegments = pathname.split('/');
179185
const passthroughIndex = pathSegments.indexOf('passthrough');
180186
if (passthroughIndex !== -1) {
181-
proxyPath = pathSegments.slice(0, passthroughIndex + 3).join('/');
187+
baseUrl = pathSegments.slice(0, passthroughIndex + 2).join('/');
182188
}
183-
}
184-
const jupyterLabConfigEl = document.getElementById('jupyter-config-data');
185-
let baseUrl;
186-
if (jupyterLabConfigEl) {
189+
} else if (jupyterLabConfigEl) {
187190
// This is jupyter lab
188191
baseUrl = JSON.parse(jupyterLabConfigEl.textContent || '').baseUrl;
189192
} else {
@@ -195,24 +198,15 @@ def get_uid_str(uid):
195198
datasets: config.datasets.map(d => ({
196199
...d,
197200
files: d.files.map(f => {
198-
// Checks to handle different scenarios of urls presented in workspaces and otherwise, i.e., local vs. remote
199-
// For regular urls
200-
let constructedUrl = f.url;
201-
// if in workspaces, only local data is accessed
202-
if (isInWorkspaces && f.url.startsWith(WORKSPACES_URL_KEYWORD)){
203-
constructedUrl = `${proxyPath}${baseUrl}${f.url}`;
204-
}
205-
else if (isInWorkspaces && !f.url.startsWith(WORKSPACES_URL_KEYWORD)){
206-
constructedUrl = f.url;
207-
}
208-
// if local data is accessed in the notebook
209-
else if (f.url.startsWith('proxy')) {
210-
constructedUrl = `${origin}${baseUrl}${f.url}`;
201+
if (isInWorkspaces && f.url.startsWith('proxy')) {
202+
// When the user is in workspaces, we do not use jupyter_server_proxy.
203+
// Instead, the workspaces infrastructure has its own "passthrough" functionality.
204+
f.url = f.url.replace('proxy', '');
211205
}
212206
return {
213207
...f,
214-
url: constructedUrl,
215-
}
208+
url: `${origin}${baseUrl}${f.url}`,
209+
};
216210
}),
217211
})),
218212
};
@@ -409,7 +403,7 @@ def get_uid_str(uid):
409403
function VitessceWidget(props) {
410404
const { model } = props;
411405
412-
const [config, setConfig] = React.useState(prependBaseUrl(model.get('config'), model.get('proxy'), model.get('has_host_name')));
406+
const [config, setConfig] = React.useState(prependBaseUrl(model.get('config'), model.get('proxy'), model.get('has_host_name'), model.get('current_port')));
413407
const [validateConfig, setValidateConfig] = React.useState(true);
414408
const height = model.get('height');
415409
const theme = model.get('theme') === 'auto' ? (prefersDark ? 'dark' : 'light') : model.get('theme');
@@ -597,6 +591,7 @@ class VitessceWidget(anywidget.AnyWidget):
597591
page_mode = Bool(False).tag(sync=True)
598592
page_esm = Unicode('').tag(sync=True)
599593
invoke_timeout = Int(300000).tag(sync=True)
594+
current_port = Int(0).tag(sync=True)
600595

601596
store_urls = List(trait=Unicode(''), default_value=[]).tag(sync=True)
602597

@@ -653,7 +648,8 @@ def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=
653648
plugin_esm=plugin_esm, remount_on_uid_change=remount_on_uid_change,
654649
page_mode=page_mode, page_esm=('' if page_esm is None else page_esm),
655650
invoke_timeout=invoke_timeout,
656-
uid=uid_str, store_urls=list(self._stores.keys())
651+
uid=uid_str, store_urls=list(self._stores.keys()),
652+
current_port=use_port
657653
)
658654

659655
# Register chained plugin on_config_change functions with a change observer.
@@ -759,6 +755,7 @@ def ipython_display(config, height=600, theme='auto', base_url=None, host_name=N
759755
"invoke_timeout": 30000,
760756
"proxy": proxy,
761757
"has_host_name": host_name is not None,
758+
"current_port": use_port,
762759
"height": height,
763760
"theme": theme,
764761
"config": config_dict,

0 commit comments

Comments
 (0)