Skip to content

Commit

Permalink
Desktop: Displays error info when Joplin Server fails
Browse files Browse the repository at this point in the history
  • Loading branch information
laurent22 committed May 21, 2021
1 parent e94503a commit 3f0586e
Showing 1 changed file with 67 additions and 57 deletions.
124 changes: 67 additions & 57 deletions packages/lib/JoplinServerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { _ } from './locale';
const { rtrimSlashes } = require('./path-utils.js');
import JoplinError from './JoplinError';
import { Env } from './models/Setting';
import Logger from './Logger';
const { stringify } = require('query-string');

const logger = Logger.create('JoplinServerApi');

interface Options {
baseUrl(): string;
username(): string;
Expand Down Expand Up @@ -133,71 +136,78 @@ export default class JoplinServerApi {
url += stringify(query);
}

let response: any = null;

if (this.debugRequests_) {
console.info('Joplin API Call', `${method} ${url}`, headers, options);
console.info(this.requestToCurl_(url, fetchOptions));
}

if (options.source == 'file' && (method == 'POST' || method == 'PUT')) {
if (fetchOptions.path) {
const fileStat = await shim.fsDriver().stat(fetchOptions.path);
if (fileStat) fetchOptions.headers['Content-Length'] = `${fileStat.size}`;
try {
if (this.debugRequests_) {
logger.debug(this.requestToCurl_(url, fetchOptions));
}
response = await shim.uploadBlob(url, fetchOptions);
} else if (options.target == 'string') {
if (typeof body === 'string') fetchOptions.headers['Content-Length'] = `${shim.stringByteLength(body)}`;
response = await shim.fetch(url, fetchOptions);
} else {
// file
response = await shim.fetchBlob(url, fetchOptions);
}

const responseText = await response.text();
let response: any = null;

if (options.source == 'file' && (method == 'POST' || method == 'PUT')) {
if (fetchOptions.path) {
const fileStat = await shim.fsDriver().stat(fetchOptions.path);
if (fileStat) fetchOptions.headers['Content-Length'] = `${fileStat.size}`;
}
response = await shim.uploadBlob(url, fetchOptions);
} else if (options.target == 'string') {
if (typeof body === 'string') fetchOptions.headers['Content-Length'] = `${shim.stringByteLength(body)}`;
response = await shim.fetch(url, fetchOptions);
} else {
// file
response = await shim.fetchBlob(url, fetchOptions);
}

if (this.debugRequests_) {
console.info('Joplin API Response', responseText);
}
const responseText = await response.text();

// Creates an error object with as much data as possible as it will appear in the log, which will make debugging easier
const newError = (message: string, code: number = 0) => {
// Gives a shorter response for error messages. Useful for cases where a full HTML page is accidentally loaded instead of
// JSON. That way the error message will still show there's a problem but without filling up the log or screen.
const shortResponseText = (`${responseText}`).substr(0, 1024);
// return new JoplinError(`${method} ${path}: ${message} (${code}): ${shortResponseText}`, code);
return new JoplinError(message, code, `${method} ${path}: ${message} (${code}): ${shortResponseText}`);
};

let responseJson_: any = null;
const loadResponseJson = async () => {
if (!responseText) return null;
if (responseJson_) return responseJson_;
responseJson_ = JSON.parse(responseText);
if (!responseJson_) throw newError('Cannot parse JSON response', response.status);
return responseJson_;
};

if (!response.ok) {
if (options.target === 'file') throw newError('fetchBlob error', response.status);

let json = null;
try {
json = await loadResponseJson();
} catch (error) {
// Just send back the plain text in newErro()
if (this.debugRequests_) {
logger.debug('Response', responseText);
}

if (json && json.error) {
throw newError(`${json.error}`, json.code ? json.code : response.status);
// Creates an error object with as much data as possible as it will appear in the log, which will make debugging easier
const newError = (message: string, code: number = 0) => {
// Gives a shorter response for error messages. Useful for cases where a full HTML page is accidentally loaded instead of
// JSON. That way the error message will still show there's a problem but without filling up the log or screen.
const shortResponseText = (`${responseText}`).substr(0, 1024);
// return new JoplinError(`${method} ${path}: ${message} (${code}): ${shortResponseText}`, code);
return new JoplinError(message, code, `${method} ${path}: ${message} (${code}): ${shortResponseText}`);
};

let responseJson_: any = null;
const loadResponseJson = async () => {
if (!responseText) return null;
if (responseJson_) return responseJson_;
responseJson_ = JSON.parse(responseText);
if (!responseJson_) throw newError('Cannot parse JSON response', response.status);
return responseJson_;
};

if (!response.ok) {
if (options.target === 'file') throw newError('fetchBlob error', response.status);

let json = null;
try {
json = await loadResponseJson();
} catch (error) {
// Just send back the plain text in newErro()
}

if (json && json.error) {
throw newError(`${json.error}`, json.code ? json.code : response.status);
}

throw newError('Unknown error', response.status);
}

throw newError('Unknown error', response.status);
}

if (options.responseFormat === 'text') return responseText;
if (options.responseFormat === 'text') return responseText;

const output = await loadResponseJson();
return output;
const output = await loadResponseJson();
return output;
} catch (error) {
if (error.code !== 404) {
logger.warn(this.requestToCurl_(url, fetchOptions));
logger.warn(error);
}
throw error;
}
}
}

0 comments on commit 3f0586e

Please sign in to comment.