Skip to content

Commit

Permalink
Merge pull request #649 from vidartf/jps2
Browse files Browse the repository at this point in the history
Jupyter server 2.0 compatability fixes
  • Loading branch information
vidartf committed Jan 15, 2023
2 parents 0d57918 + 498ae07 commit 2da614b
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 34 deletions.
64 changes: 42 additions & 22 deletions nbdime/tests/test_cli_apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ def test_git_mergedriver(git_repo, filespath):


@pytest.mark.timeout(timeout=3*WEB_TEST_TIMEOUT)
def test_git_difftool(git_repo, unique_port, popen_with_terminator, auth_header):
def test_git_difftool(git_repo, unique_port, popen_with_terminator):
gitdifftool.main(['config', '--enable'])
cmd = get_output('git config --get --local difftool.nbdime.cmd').strip()

Expand All @@ -605,10 +605,14 @@ def test_git_difftool(git_repo, unique_port, popen_with_terminator, auth_header)
for _ in range(3):
wait_up(url, check=lambda: process.poll() is None)
# server started
r = requests.get(url + '/difftool')
s = requests.Session()
r = s.get(url + '/difftool')
r.raise_for_status()
# close it
r = requests.post(url + '/api/closetool', json={'exitCode': 0}, headers=auth_header)
r = s.post(url + '/api/closetool', data={
'exitCode': 0,
'_xsrf': r.cookies['_xsrf']
})
r.raise_for_status()
time.sleep(0.25)
# wait for exit
Expand All @@ -617,7 +621,7 @@ def test_git_difftool(git_repo, unique_port, popen_with_terminator, auth_header)


@pytest.mark.timeout(timeout=3*WEB_TEST_TIMEOUT)
def test_git_mergetool(git_repo, unique_port, popen_with_terminator, auth_header):
def test_git_mergetool(git_repo, unique_port, popen_with_terminator):
gitmergetool.main(['config', '--enable'])
cmd = get_output('git config --get --local mergetool.nbdime.cmd').strip()

Expand All @@ -636,18 +640,24 @@ def test_git_mergetool(git_repo, unique_port, popen_with_terminator, auth_header
url = 'http://127.0.0.1:%i' % port
wait_up(url, check=lambda: process.poll() is None)
# server started
r = requests.get(url + '/mergetool')
s = requests.Session()
r = s.get(url + '/mergetool')
r.raise_for_status()
r = requests.post(
xsrf = r.cookies['_xsrf']
r = s.post(
url_concat(url + '/api/store', {'outputfilename': 'merge-conflict.ipynb'}),
data=json.dumps({
'merged': nbformat.v4.new_notebook(),
}),
headers=auth_header
json={'merged': nbformat.v4.new_notebook()},
headers={'X-XSRFToken': xsrf},
)
r.raise_for_status()
# close it
r = requests.post(url + '/api/closetool', json={'exitCode': 0}, headers=auth_header)
r = s.post(
url + '/api/closetool',
data={
'exitCode': 0,
'_xsrf': xsrf,
}
)
r.raise_for_status()
# wait for exit
process.wait()
Expand Down Expand Up @@ -694,7 +704,7 @@ def test_hg_mergedriver(hg_repo, filespath, reset_log):


@pytest.mark.timeout(timeout=3*WEB_TEST_TIMEOUT)
def test_hg_diffweb(hg_repo, unique_port, popen_with_terminator, auth_header):
def test_hg_diffweb(hg_repo, unique_port, popen_with_terminator):
# enable diff/merge drivers
write_local_hg_config(hg_repo)

Expand All @@ -706,10 +716,14 @@ def test_hg_diffweb(hg_repo, unique_port, popen_with_terminator, auth_header):
wait_up(url, check=lambda: process.poll() is None)
for _ in range(3):
# server started
r = requests.get(url + '/difftool')
s = requests.Session()
r = s.get(url + '/difftool')
r.raise_for_status()
# close it
r = requests.post(url + '/api/closetool', json={'exitCode': 0}, headers=auth_header)
r = s.post(url + '/api/closetool', data={
'exitCode': 0,
'_xsrf': r.cookies['_xsrf']
})
r.raise_for_status()
time.sleep(0.25)
# wait for exit
Expand All @@ -718,7 +732,7 @@ def test_hg_diffweb(hg_repo, unique_port, popen_with_terminator, auth_header):


@pytest.mark.timeout(timeout=WEB_TEST_TIMEOUT)
def test_hg_mergetool(hg_repo, unique_port, popen_with_terminator, auth_header):
def test_hg_mergetool(hg_repo, unique_port, popen_with_terminator):
# enable diff/merge drivers
write_local_hg_config(hg_repo)

Expand All @@ -733,18 +747,24 @@ def test_hg_mergetool(hg_repo, unique_port, popen_with_terminator, auth_header):
url = 'http://127.0.0.1:%i' % unique_port
wait_up(url, check=lambda: process.poll() is None)
# server started
r = requests.get(url + '/mergetool')
s = requests.Session()
r = s.get(url + '/mergetool')
r.raise_for_status()
r = requests.post(
xsrf = r.cookies['_xsrf']
r = s.post(
url_concat(url + '/api/store', {'outputfilename': 'merge-conflict.ipynb'}),
data=json.dumps({
'merged': nbformat.v4.new_notebook(),
}),
headers=auth_header
json={'merged': nbformat.v4.new_notebook()},
headers={'X-XSRFToken': xsrf},
)
r.raise_for_status()
# close it
r = requests.post(url + '/api/closetool', json={'exitCode': 0}, headers=auth_header)
r = s.post(
url + '/api/closetool',
data={
'exitCode': 0,
'_xsrf': xsrf
}
)
r.raise_for_status()
# wait for exit
process.wait()
Expand Down
18 changes: 12 additions & 6 deletions nbdime/tests/test_server_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
def test_isgit(git_repo2, server_extension_app):
url = 'http://127.0.0.1:%i/nbdime/api/isgit' % server_extension_app['port']
r = requests.post(
url, headers=auth_header,
url,
headers=auth_header,
data=json.dumps({
'path': git_repo2,
}))
Expand All @@ -45,7 +46,8 @@ def test_isgit(git_repo2, server_extension_app):
def test_isgit_nonrepo(git_repo2, server_extension_app):
url = 'http://127.0.0.1:%i/nbdime/api/isgit' % server_extension_app['port']
r = requests.post(
url, headers=auth_header,
url,
headers=auth_header,
data=json.dumps({
'path': server_extension_app['path'],
}))
Expand All @@ -64,7 +66,8 @@ def test_difftool(git_repo2, server_extension_app):
def test_git_difftool(git_repo2, server_extension_app):
url = 'http://127.0.0.1:%i/nbdime/git-difftool' % server_extension_app['port']
r = requests.get(
url, headers=auth_header)
url,
headers=auth_header)
r.raise_for_status()
assert r.text.startswith('<!DOCTYPE html')
# Extract config data
Expand All @@ -87,7 +90,8 @@ def test_diff_api(git_repo2, server_extension_app):
local_path = os.path.relpath(git_repo2, server_extension_app['path'])
url = 'http://127.0.0.1:%i/nbdime/api/diff' % server_extension_app['port']
r = requests.post(
url, headers=auth_header,
url,
headers=auth_header,
data=json.dumps({
'base': 'git:' + pjoin(local_path, 'diff.ipynb'),
}))
Expand Down Expand Up @@ -124,7 +128,8 @@ def _make_ref(key):
):
print(args)
r = requests.post(
url, headers=auth_header,
url,
headers=auth_header,
data=json.dumps({
'ref_local': _make_ref(args[0]),
'ref_remote': _make_ref(args[1]),
Expand Down Expand Up @@ -193,7 +198,8 @@ def test_diff_api_symlink(git_repo2, server_extension_app, needs_symlink):
local_path = os.path.relpath(symlink, server_extension_app['path'])
url = 'http://127.0.0.1:%i/nbdime/api/diff' % server_extension_app['port']
r = requests.post(
url, headers=auth_header,
url,
headers=auth_header,
data=json.dumps({
'base': 'git:' + pjoin(local_path, 'diff.ipynb'),
}))
Expand Down
22 changes: 17 additions & 5 deletions nbdime/webapp/nbdimeserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,17 @@ def post(self):
# Fail if no exit code is supplied:
fallback = int(self.request.headers.get('exit_code', 1))
try:
self.application.exit_code = json.loads(self.request.body).get('exitCode', fallback)
except json.JSONDecodeError:
self.application.exit_code = fallback

_logger.info('Closing server on remote request')
self.application.exit_code = self.get_argument('exitCode')
except web.MissingArgumentError:
try:
self.application.exit_code = json.loads(self.request.body).get('exitCode', fallback)
except json.JSONDecodeError:
self.application.exit_code = fallback

if isinstance(self.application.exit_code, str):
self.application.exit_code = int(self.application.exit_code, 10)

_logger.info('Closing server on remote request (%d)', self.application.exit_code)
self.finish()
ioloop.IOLoop.current().stop()

Expand Down Expand Up @@ -387,6 +393,12 @@ def make_app(**params):
'cookie_secret': base64.encodebytes(os.urandom(32)), # Needed even for an unsecured server.
}

try:
from jupyter_server.auth import IdentityProvider
settings['identity_provider'] = IdentityProvider()
except ImportError:
pass

if is_in_repo(nbdime_root):
# don't cache when working from repo
settings.update({
Expand Down
35 changes: 34 additions & 1 deletion packages/webapp/src/app/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {
URLExt
} from '@jupyterlab/coreutils/lib/url';

import type {
PartialJSONObject
} from '@lumino/coreutils';

import type {
Widget
} from '@lumino/widgets';
Expand Down Expand Up @@ -209,6 +213,35 @@ function markUnchangedRanges() {
}


/**
* Get the XSRF token from the cookie, if present
*/
function getXsrfToken(): string | undefined {
const r = document.cookie.match(/\b_xsrf=([^;]*)\b/);
return r ? r[1] : undefined;
}


/**
* Wrap a navigator.sendBeacon call with XSRF data
*/
function sendBeacon(url: string, data: PartialJSONObject): void {
const formData = new FormData();
const token = getXsrfToken();
if (token) {
formData.append('_xsrf', token);
}

for (let key of Object.keys(data)) {
if (data[key]) {
formData.append(key, data[key]!.toString() );
}
}

navigator.sendBeacon(url, formData);
}


export let toolClosed = false;
/**
* POSTs to the server that it should shut down if it was launched as a
Expand All @@ -222,7 +255,7 @@ function closeTool(exitCode=0) {
if (!toolClosed) {
toolClosed = true;
let url = '/api/closetool';
navigator.sendBeacon(url, JSON.stringify({exitCode}));
sendBeacon(url, {exitCode});
window.close();
}
}
Expand Down

0 comments on commit 2da614b

Please sign in to comment.