Fix WS connection getting closed

This commit is contained in:
fflorent 2024-03-26 20:21:28 +01:00
parent ef6957a92c
commit e4e0ffe2cc
2 changed files with 46 additions and 18 deletions

View File

@ -777,7 +777,7 @@ export class UserAPIImpl extends BaseAPI implements UserAPI {
method: 'GET', method: 'GET',
credentials: 'include' credentials: 'include'
}); });
return getDocWorkerUrl(this._homeUrl, json); return getPublicDocWorkerUrl(this._homeUrl, json);
} }
public async getWorkerAPI(key: string): Promise<DocWorkerAPI> { public async getWorkerAPI(key: string): Promise<DocWorkerAPI> {
@ -1156,6 +1156,22 @@ export class DocAPIImpl extends BaseAPI implements DocAPI {
} }
} }
interface DocWorkerInfo {
docWorkerUrl: string|null;
internalDocWorkerUrl: string|null;
selfPrefix?: string;
}
function getUrlFromPrefix(homeUrl: string, prefix?: string) {
if (!prefix) {
// This should never happen.
throw new Error('missing selfPrefix for docWorkerUrl');
}
const url = new URL(homeUrl);
url.pathname = prefix + url.pathname;
return url.href;
}
/** /**
* Get a docWorkerUrl from information returned from backend. When the backend * Get a docWorkerUrl from information returned from backend. When the backend
* is fully configured, and there is a pool of workers, this is straightforward, * is fully configured, and there is a pool of workers, this is straightforward,
@ -1164,20 +1180,32 @@ export class DocAPIImpl extends BaseAPI implements DocAPI {
* use the homeUrl of the backend, with extra path prefix information * use the homeUrl of the backend, with extra path prefix information
* given by selfPrefix. At the time of writing, the selfPrefix contains a * given by selfPrefix. At the time of writing, the selfPrefix contains a
* doc-worker id, and a tag for the codebase (used in consistency checks). * doc-worker id, and a tag for the codebase (used in consistency checks).
*
* @param {string} homeUrl
* @param {object} docWorkerInfo
* @param {string} docWorkerInfo.docWorkerUrl The public doc Worker URL
* @param {string} docWorkerInfo.internalDocWorkerUrl The internal doc Worker URL
* @param {string|undefined} docWorkerInfo.selfPrefix
* @param {string} urlType The type of doc worker url to extract from the docWorkerInfo
*/ */
export function getDocWorkerUrl(homeUrl: string, docWorkerInfo: { export function getPublicDocWorkerUrl(homeUrl: string, docWorkerInfo: DocWorkerInfo) {
docWorkerUrl: string|null, const publicUrl = docWorkerInfo.docWorkerUrl;
internalDocWorkerUrl: string|null, return publicUrl || getUrlFromPrefix(homeUrl, docWorkerInfo.selfPrefix);
selfPrefix?: string, }
}): string {
if (!docWorkerInfo.docWorkerUrl) { /**
if (!docWorkerInfo.selfPrefix) { * @see getPublicDocWorkerUrl
// This should never happen. * Like getPublicDocWorkerUrl but returns the URL resolvable internally (behind a Reverse Proxy).
throw new Error('missing selfPrefix for docWorkerUrl'); * Especially useful when and where the public url cannot be resolved.
} *
const url = new URL(homeUrl); * @param {string} homeUrl
url.pathname = docWorkerInfo.selfPrefix + url.pathname; * @param {object} docWorkerInfo
return url.href; * @param {string} docWorkerInfo.docWorkerUrl The public doc Worker URL
} * @param {string} docWorkerInfo.internalDocWorkerUrl The internal doc Worker URL
return docWorkerInfo.internalDocWorkerUrl || docWorkerInfo.docWorkerUrl; * @param {string|undefined} docWorkerInfo.selfPrefix
* @param {string} urlType The type of doc worker url to extract from the docWorkerInfo
*/
export function getInternalDocWorkerUrl(homeUrl: string, docWorkerInfo: DocWorkerInfo) {
const internalUrl = docWorkerInfo.internalDocWorkerUrl;
return internalUrl || getUrlFromPrefix(homeUrl, docWorkerInfo.selfPrefix);
} }

View File

@ -1,7 +1,7 @@
import {ApiError} from 'app/common/ApiError'; import {ApiError} from 'app/common/ApiError';
import {InactivityTimer} from 'app/common/InactivityTimer'; import {InactivityTimer} from 'app/common/InactivityTimer';
import {FetchUrlOptions, FileUploadResult, UPLOAD_URL_PATH, UploadResult} from 'app/common/uploads'; import {FetchUrlOptions, FileUploadResult, UPLOAD_URL_PATH, UploadResult} from 'app/common/uploads';
import {getDocWorkerUrl} from 'app/common/UserAPI'; import {getInternalDocWorkerUrl} from 'app/common/UserAPI';
import {getAuthorizedUserId, getTransitiveHeaders, getUserId, isSingleUserMode, import {getAuthorizedUserId, getTransitiveHeaders, getUserId, isSingleUserMode,
RequestWithLogin} from 'app/server/lib/Authorizer'; RequestWithLogin} from 'app/server/lib/Authorizer';
import {expressWrap} from 'app/server/lib/expressWrap'; import {expressWrap} from 'app/server/lib/expressWrap';
@ -421,7 +421,7 @@ export async function fetchDoc(server: GristServer, docId: string, req: Request,
const fetchUrl = new URL(`/api/worker/${docId}`, homeUrl); const fetchUrl = new URL(`/api/worker/${docId}`, homeUrl);
const response: FetchResponse = await Deps.fetch(fetchUrl.href, {headers}); const response: FetchResponse = await Deps.fetch(fetchUrl.href, {headers});
await _checkForError(response); await _checkForError(response);
const docWorkerUrl = getDocWorkerUrl(server.getOwnUrl(), await response.json()); const docWorkerUrl = getInternalDocWorkerUrl(server.getOwnUrl(), await response.json());
// Download the document, in full or as a template. // Download the document, in full or as a template.
const url = new URL(`api/docs/${docId}/download?template=${Number(template)}`, const url = new URL(`api/docs/${docId}/download?template=${Number(template)}`,
docWorkerUrl.replace(/\/*$/, '/')); docWorkerUrl.replace(/\/*$/, '/'));