通常一个新的 Notebook 在打开的时候,会自动连接当前服务器,创建一个 Session 和一个 Kernel 进程。该 Session 绑定在该 nb(notebook 简称,下同) 的路径上,因此你要你的 server 不停,无论刷新 nb 还是打开该 nb 的一个新 tab,该 session 都是同一个 session,kernel 也是同一个 kernel。
以上是 Notebook 基本的前后端交互流程,本文关注的是当 nb 与 Kernel 不在同一个域下时,如何跨域连接的问题。即假设 nb 的地址是 a.com/xx.ipynb
,但我们想连接 b.com
的一个 kernel。
修改后端地址
首先是创建 Session 的调用,该调用发生在 session.js
第 122 行
utils.ajax(this.session_service_url, {
这里需要修改为你想要连接的域名,比如 'http://b.com' + this.session_service_url
。
session 与 kernel 创建完成后,nb 与 kernel 的交互会使用 websocket 通道。ws 地址是类似 ws://localhost
这样的格式,定义在 notebook.html
模板中,在打开 nb 时由 server 进行渲染:
data-ws-url="{{ws_url | urlencode}}"
这两处修改为跨域地址后,你的 nb 就会自动向新服务器发请求,那么自然你的新服务器需要在响应中添加跨域头,这一点可以简单通过修改配置文件实现:
c.NotebookApp.allow_origin = '*'
该配置项会在 /base/handlers.py
中被访问:
[@property](https://my.oschina.net/property)
def allow_origin(self):
"""Normal Access-Control-Allow-Origin"""
return self.settings.get('allow_origin', '')
处理认证
当然 server 不是对连接来者不拒的。在认证上仍有两处需要处理:
一是 xsrf token 认证,该认证可以在配置文件中关掉:
c.NotebookApp.disable_check_xsrf = True
二是用户登录认证。server 默认使用 token 的方式,该 token 会在渲染 nb 的时候写入 page.html
里:
data-jupyter-api-token="{{token | urlencode}}"
或者想直接绕过 auth 过程的话,修改 base/handlers.py
里的 get_current_user
方法即可。
完成以上修改后,跨域连接 kernel 的功能就可以实现了。