Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit51dae23

Browse files
authored
Merge pull requestjupyter#4260 from takluyver/browser-open-file
Launch the browser with a redirect file
2 parentsf759e4d +56d7a2d commit51dae23

File tree

5 files changed

+99
-49
lines changed

5 files changed

+99
-49
lines changed

‎notebook/auth/login.py‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,11 @@ def get_user_token(cls, handler):
204204
return
205205
# check login token from URL argument or Authorization header
206206
user_token=cls.get_token(handler)
207-
one_time_token=handler.one_time_token
208207
authenticated=False
209208
ifuser_token==token:
210209
# token-authenticated, set the login cookie
211210
handler.log.debug("Accepting token-authenticated connection from %s",handler.request.remote_ip)
212211
authenticated=True
213-
elifone_time_tokenanduser_token==one_time_token:
214-
# one-time-token-authenticated, only allow this token once
215-
handler.settings.pop('one_time_token',None)
216-
handler.log.info("Accepting one-time-token-authenticated connection from %s",handler.request.remote_ip)
217-
authenticated=True
218212

219213
ifauthenticated:
220214
returnuuid.uuid4().hex

‎notebook/base/handlers.py‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,6 @@ def token(self):
180180
"""Return the login token for this application, if any."""
181181
returnself.settings.get('token',None)
182182

183-
@property
184-
defone_time_token(self):
185-
"""Return the one-time-use token for this application, if any."""
186-
returnself.settings.get('one_time_token',None)
187-
188183
@property
189184
deflogin_available(self):
190185
"""May a user proceed to log in?
@@ -475,7 +470,7 @@ def template_namespace(self):
475470
logged_in=self.logged_in,
476471
allow_password_change=self.settings.get('allow_password_change'),
477472
login_available=self.login_available,
478-
token_available=bool(self.tokenorself.one_time_token),
473+
token_available=bool(self.token),
479474
static_url=self.static_url,
480475
sys_info=json_sys_info(),
481476
contents_js_source=self.contents_js_source,

‎notebook/notebookapp.py‎

Lines changed: 76 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
importsignal
2727
importsocket
2828
importsys
29+
importtempfile
2930
importthreading
3031
importtime
3132
importwarnings
@@ -107,7 +108,7 @@
107108
fromnotebook._sysinfoimportget_sys_info
108109

109110
from ._tzimportutcnow,utcfromtimestamp
110-
from .utilsimporturl_path_join,check_pid,url_escape
111+
from .utilsimporturl_path_join,check_pid,url_escape,urljoin,pathname2url
111112

112113
#-----------------------------------------------------------------------------
113114
# Module globals
@@ -754,12 +755,6 @@ def _write_cookie_secret_file(self, secret):
754755
""")
755756
).tag(config=True)
756757

757-
one_time_token=Unicode(
758-
help=_("""One-time token used for opening a browser.
759-
Once used, this token cannot be used again.
760-
""")
761-
)
762-
763758
_token_generated=True
764759

765760
@default('token')
@@ -1184,6 +1179,13 @@ def _update_mathjax_config(self, change):
11841179
def_default_info_file(self):
11851180
info_file="nbserver-%s.json"%os.getpid()
11861181
returnos.path.join(self.runtime_dir,info_file)
1182+
1183+
browser_open_file=Unicode()
1184+
1185+
@default('browser_open_file')
1186+
def_default_browser_open_file(self):
1187+
basename="nbserver-%s-open.html"%os.getpid()
1188+
returnos.path.join(self.runtime_dir,basename)
11871189

11881190
pylab=Unicode('disabled',config=True,
11891191
help=_("""
@@ -1363,9 +1365,6 @@ def init_webapp(self):
13631365
self.tornado_settings['cookie_options']=self.cookie_options
13641366
self.tornado_settings['get_secure_cookie_kwargs']=self.get_secure_cookie_kwargs
13651367
self.tornado_settings['token']=self.token
1366-
if (self.open_browserorself.file_to_run)andnotself.password:
1367-
self.one_time_token=binascii.hexlify(os.urandom(24)).decode('ascii')
1368-
self.tornado_settings['one_time_token']=self.one_time_token
13691368

13701369
# ensure default_url starts with base_url
13711370
ifnotself.default_url.startswith(self.base_url):
@@ -1697,6 +1696,67 @@ def remove_server_info_file(self):
16971696
ife.errno!=errno.ENOENT:
16981697
raise
16991698

1699+
defwrite_browser_open_file(self):
1700+
"""Write an nbserver-<pid>-open.html file
1701+
1702+
This can be used to open the notebook in a browser
1703+
"""
1704+
# default_url contains base_url, but so does connection_url
1705+
open_url=self.default_url[len(self.base_url):]
1706+
1707+
withopen(self.browser_open_file,'w',encoding='utf-8')asf:
1708+
self._write_browser_open_file(open_url,f)
1709+
1710+
def_write_browser_open_file(self,url,fh):
1711+
ifself.token:
1712+
url=url_concat(url, {'token':self.token})
1713+
url=url_path_join(self.connection_url,url)
1714+
1715+
jinja2_env=self.web_app.settings['jinja2_env']
1716+
template=jinja2_env.get_template('browser-open.html')
1717+
fh.write(template.render(open_url=url))
1718+
1719+
defremove_browser_open_file(self):
1720+
"""Remove the nbserver-<pid>-open.html file created for this server.
1721+
1722+
Ignores the error raised when the file has already been removed.
1723+
"""
1724+
try:
1725+
os.unlink(self.browser_open_file)
1726+
exceptOSErrorase:
1727+
ife.errno!=errno.ENOENT:
1728+
raise
1729+
1730+
deflaunch_browser(self):
1731+
try:
1732+
browser=webbrowser.get(self.browserorNone)
1733+
exceptwebbrowser.Errorase:
1734+
self.log.warning(_('No web browser found: %s.')%e)
1735+
browser=None
1736+
1737+
ifnotbrowser:
1738+
return
1739+
1740+
ifself.file_to_run:
1741+
ifnotos.path.exists(self.file_to_run):
1742+
self.log.critical(_("%s does not exist")%self.file_to_run)
1743+
self.exit(1)
1744+
1745+
relpath=os.path.relpath(self.file_to_run,self.notebook_dir)
1746+
uri=url_escape(url_path_join('notebooks',*relpath.split(os.sep)))
1747+
1748+
# Write a temporary file to open in the browser
1749+
fd,open_file=tempfile.mkstemp(suffix='.html')
1750+
withopen(fd,'w',encoding='utf-8')asfh:
1751+
self._write_browser_open_file(uri,fh)
1752+
else:
1753+
open_file=self.browser_open_file
1754+
1755+
b=lambda:browser.open(
1756+
urljoin('file:',pathname2url(open_file)),
1757+
new=self.webbrowser_open_new)
1758+
threading.Thread(target=b).start()
1759+
17001760
defstart(self):
17011761
""" Start the Notebook server app, after initialization
17021762
@@ -1726,38 +1786,19 @@ def start(self):
17261786
"resources section at https://jupyter.org/community.html."))
17271787

17281788
self.write_server_info_file()
1789+
self.write_browser_open_file()
17291790

17301791
ifself.open_browserorself.file_to_run:
1731-
try:
1732-
browser=webbrowser.get(self.browserorNone)
1733-
exceptwebbrowser.Errorase:
1734-
self.log.warning(_('No web browser found: %s.')%e)
1735-
browser=None
1736-
1737-
ifself.file_to_run:
1738-
ifnotos.path.exists(self.file_to_run):
1739-
self.log.critical(_("%s does not exist")%self.file_to_run)
1740-
self.exit(1)
1741-
1742-
relpath=os.path.relpath(self.file_to_run,self.notebook_dir)
1743-
uri=url_escape(url_path_join('notebooks',*relpath.split(os.sep)))
1744-
else:
1745-
# default_url contains base_url, but so does connection_url
1746-
uri=self.default_url[len(self.base_url):]
1747-
ifself.one_time_token:
1748-
uri=url_concat(uri, {'token':self.one_time_token})
1749-
ifbrowser:
1750-
b=lambda :browser.open(url_path_join(self.connection_url,uri),
1751-
new=self.webbrowser_open_new)
1752-
threading.Thread(target=b).start()
1792+
self.launch_browser()
17531793

17541794
ifself.tokenandself._token_generated:
17551795
# log full URL with generated token, so there's a copy/pasteable link
17561796
# with auth info.
17571797
self.log.critical('\n'.join([
17581798
'\n',
1759-
'Copy/paste this URL into your browser when you connect for the first time,',
1760-
'to login with a token:',
1799+
'To access the notebook, open this file in a browser:',
1800+
' %s'%urljoin('file:',pathname2url(self.browser_open_file)),
1801+
'Or copy and paste one of these URLs:',
17611802
' %s'%self.display_url,
17621803
]))
17631804

@@ -1773,6 +1814,7 @@ def start(self):
17731814
info(_("Interrupted..."))
17741815
finally:
17751816
self.remove_server_info_file()
1817+
self.remove_browser_open_file()
17761818
self.cleanup_kernels()
17771819

17781820
defstop(self):
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{# This template is not served, but written as a file to open in the browser,
2+
passing the token without putting it in a command-line argument. #}
3+
<!DOCTYPE html>
4+
<htmllang="en">
5+
<head>
6+
<metacharset="UTF-8">
7+
<metahttp-equiv="refresh"content="1;url={{ open_url }}"/>
8+
<title>Opening Jupyter Notebook</title>
9+
</head>
10+
<body>
11+
12+
<p>
13+
This page should redirect you to Jupyter Notebook. If it doesn't,
14+
<ahref="{{ open_url }}">click here to go to Jupyter</a>.
15+
</p>
16+
17+
</body>
18+
</html>

‎notebook/utils.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
fromdistutils.versionimportLooseVersion
1414

1515
try:
16-
fromurllib.parseimportquote,unquote,urlparse
16+
fromurllib.parseimportquote,unquote,urlparse,urljoin
17+
fromurllib.requestimportpathname2url
1718
exceptImportError:
18-
fromurllibimportquote,unquote
19-
fromurlparseimporturlparse
19+
fromurllibimportquote,unquote,pathname2url
20+
fromurlparseimporturlparse,urljoin
2021

2122
fromipython_genutilsimportpy3compat
2223

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp