1 | "use strict";
|
2 |
|
3 |
|
4 | var _a, _b, _c;
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.ServerConnection = void 0;
|
7 | const coreutils_1 = require("@jupyterlab/coreutils");
|
8 | let FETCH;
|
9 | let HEADERS;
|
10 | let REQUEST;
|
11 | let WEBSOCKET;
|
12 | if (typeof window === 'undefined') {
|
13 |
|
14 |
|
15 |
|
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 |
|
22 | }
|
23 | else {
|
24 | FETCH = fetch;
|
25 | REQUEST = Request;
|
26 | HEADERS = Headers;
|
27 | WEBSOCKET = WebSocket;
|
28 | }
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | var ServerConnection;
|
44 | (function (ServerConnection) {
|
45 | |
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | function makeSettings(options) {
|
53 | return Private.makeSettings(options);
|
54 | }
|
55 | ServerConnection.makeSettings = makeSettings;
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 | function makeRequest(url, init, settings) {
|
77 | return Private.handleRequest(url, init, settings);
|
78 | }
|
79 | ServerConnection.makeRequest = makeRequest;
|
80 | |
81 |
|
82 |
|
83 | class ResponseError extends Error {
|
84 | |
85 |
|
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 | */
|
135 | var 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 |