UNPKG

9.05 kBJavaScriptView Raw
1"use strict";
2// Copyright (c) Jupyter Development Team.
3// Distributed under the terms of the Modified BSD License.
4var _a, _b, _c;
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.ServerConnection = void 0;
7const coreutils_1 = require("@jupyterlab/coreutils");
8let FETCH;
9let HEADERS;
10let REQUEST;
11let WEBSOCKET;
12if (typeof window === 'undefined') {
13 // Mangle the require statements so it does not get picked up in the
14 // browser assets.
15 /* tslint:disable */
16 const fetchMod = require('node-fetch');
17 FETCH = (_a = global.fetch) !== null && _a !== void 0 ? _a : fetchMod;
18 REQUEST = (_b = global.Request) !== null && _b !== void 0 ? _b : fetchMod.Request;
19 HEADERS = (_c = global.Headers) !== null && _c !== void 0 ? _c : fetchMod.Headers;
20 WEBSOCKET = require('ws');
21 /* tslint:enable */
22}
23else {
24 FETCH = fetch;
25 REQUEST = Request;
26 HEADERS = Headers;
27 WEBSOCKET = WebSocket;
28}
29/**
30 * The namespace for ServerConnection functions.
31 *
32 * #### Notes
33 * This is only intended to manage communication with the Jupyter server.
34 *
35 * The default values can be used in a JupyterLab or Jupyter Notebook context.
36 *
37 * We use `token` authentication if available, falling back on an XSRF
38 * cookie if one has been provided on the `document`.
39 *
40 * A content type of `'application/json'` is added when using authentication
41 * and there is no body data to allow the server to prevent malicious forms.
42 */
43var ServerConnection;
44(function (ServerConnection) {
45 /**
46 * Create a settings object given a subset of options.
47 *
48 * @param options - An optional partial set of options.
49 *
50 * @returns The full settings object.
51 */
52 function makeSettings(options) {
53 return Private.makeSettings(options);
54 }
55 ServerConnection.makeSettings = makeSettings;
56 /**
57 * Make an request to the notebook server.
58 *
59 * @param url - The url for the request.
60 *
61 * @param init - The initialization options for the request.
62 *
63 * @param settings - The server settings to apply to the request.
64 *
65 * @returns a Promise that resolves with the response.
66 *
67 * @throws If the url of the request is not a notebook server url.
68 *
69 * #### Notes
70 * The `url` must start with `settings.baseUrl`. The `init` settings are
71 * merged with `settings.init`, with `init` taking precedence.
72 * The headers in the two objects are not merged.
73 * If there is no body data, we set the content type to `application/json`
74 * because it is required by the Notebook server.
75 */
76 function makeRequest(url, init, settings) {
77 return Private.handleRequest(url, init, settings);
78 }
79 ServerConnection.makeRequest = makeRequest;
80 /**
81 * A wrapped error for a fetch response.
82 */
83 class ResponseError extends Error {
84 /**
85 * Create a new response error.
86 */
87 constructor(response, message = `Invalid response: ${response.status} ${response.statusText}`, traceback = '') {
88 super(message);
89 this.response = response;
90 this.traceback = traceback;
91 }
92 /**
93 * Create a ResponseError from a response, handling the traceback and message
94 * as appropriate.
95 *
96 * @param response The response object.
97 *
98 * @returns A promise that resolves with a `ResponseError` object.
99 */
100 static async create(response) {
101 try {
102 const data = await response.json();
103 if (data['traceback']) {
104 console.error(data['traceback']);
105 }
106 if (data['message']) {
107 return new ResponseError(response, data['message']);
108 }
109 return new ResponseError(response);
110 }
111 catch (e) {
112 console.debug(e);
113 return new ResponseError(response);
114 }
115 }
116 }
117 ServerConnection.ResponseError = ResponseError;
118 /**
119 * A wrapped error for a network error.
120 */
121 class NetworkError extends TypeError {
122 /**
123 * Create a new network error.
124 */
125 constructor(original) {
126 super(original.message);
127 this.stack = original.stack;
128 }
129 }
130 ServerConnection.NetworkError = NetworkError;
131})(ServerConnection = exports.ServerConnection || (exports.ServerConnection = {}));
132/**
133 * The namespace for module private data.
134 */
135var Private;
136(function (Private) {
137 /**
138 * Handle the server connection settings, returning a new value.
139 */
140 function makeSettings(options = {}) {
141 var _a;
142 const pageBaseUrl = coreutils_1.PageConfig.getBaseUrl();
143 const pageWsUrl = coreutils_1.PageConfig.getWsUrl();
144 const baseUrl = coreutils_1.URLExt.normalize(options.baseUrl) || pageBaseUrl;
145 let wsUrl = options.wsUrl;
146 // Prefer the default wsUrl if we are using the default baseUrl.
147 if (!wsUrl && baseUrl === pageBaseUrl) {
148 wsUrl = pageWsUrl;
149 }
150 // Otherwise convert the baseUrl to a wsUrl if possible.
151 if (!wsUrl && baseUrl.indexOf('http') === 0) {
152 wsUrl = 'ws' + baseUrl.slice(4);
153 }
154 // Otherwise fall back on the default wsUrl.
155 wsUrl = wsUrl !== null && wsUrl !== void 0 ? wsUrl : pageWsUrl;
156 return Object.assign(Object.assign({ init: { cache: 'no-store', credentials: 'same-origin' }, fetch: FETCH, Headers: HEADERS, Request: REQUEST, WebSocket: WEBSOCKET, token: coreutils_1.PageConfig.getToken(), appUrl: coreutils_1.PageConfig.getOption('appUrl'), appendToken: typeof window === 'undefined' ||
157 (typeof process !== 'undefined' &&
158 ((_a = process === null || process === void 0 ? void 0 : process.env) === null || _a === void 0 ? void 0 : _a.JEST_WORKER_ID) !== undefined) ||
159 coreutils_1.URLExt.getHostName(pageBaseUrl) !== coreutils_1.URLExt.getHostName(wsUrl) }, options), { baseUrl,
160 wsUrl });
161 }
162 Private.makeSettings = makeSettings;
163 /**
164 * Handle a request.
165 *
166 * @param url - The url for the request.
167 *
168 * @param init - The overrides for the request init.
169 *
170 * @param settings - The settings object for the request.
171 *
172 * #### Notes
173 * The `url` must start with `settings.baseUrl`. The `init` settings
174 * take precedence over `settings.init`.
175 */
176 function handleRequest(url, init, settings) {
177 var _a;
178 // Handle notebook server requests.
179 if (url.indexOf(settings.baseUrl) !== 0) {
180 throw new Error('Can only be used for notebook server requests');
181 }
182 // Use explicit cache buster when `no-store` is set since
183 // not all browsers use it properly.
184 const cache = (_a = init.cache) !== null && _a !== void 0 ? _a : settings.init.cache;
185 if (cache === 'no-store') {
186 // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache
187 url += (/\?/.test(url) ? '&' : '?') + new Date().getTime();
188 }
189 const request = new settings.Request(url, Object.assign(Object.assign({}, settings.init), init));
190 // Handle authentication. Authentication can be overdetermined by
191 // settings token and XSRF token.
192 let authenticated = false;
193 if (settings.token) {
194 authenticated = true;
195 request.headers.append('Authorization', `token ${settings.token}`);
196 }
197 if (typeof document !== 'undefined' && (document === null || document === void 0 ? void 0 : document.cookie)) {
198 const xsrfToken = getCookie('_xsrf');
199 if (xsrfToken !== undefined) {
200 authenticated = true;
201 request.headers.append('X-XSRFToken', xsrfToken);
202 }
203 }
204 // Set the content type if there is no given data and we are
205 // using an authenticated connection.
206 if (!request.headers.has('Content-Type') && authenticated) {
207 request.headers.set('Content-Type', 'application/json');
208 }
209 // Use `call` to avoid a `TypeError` in the browser.
210 return settings.fetch.call(null, request).catch((e) => {
211 // Convert the TypeError into a more specific error.
212 throw new ServerConnection.NetworkError(e);
213 });
214 // TODO: *this* is probably where we need a system-wide connectionFailure
215 // signal we can hook into.
216 }
217 Private.handleRequest = handleRequest;
218 /**
219 * Get a cookie from the document.
220 */
221 function getCookie(name) {
222 // From http://www.tornadoweb.org/en/stable/guide/security.html
223 const matches = document.cookie.match('\\b' + name + '=([^;]*)\\b');
224 return matches === null || matches === void 0 ? void 0 : matches[1];
225 }
226})(Private || (Private = {}));
227//# sourceMappingURL=serverconnection.js.map
\No newline at end of file