1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-21 09:38:01 +02:00

All: Resolves #5754: Improved error message when synchronising with Joplin Server

This commit is contained in:
Laurent Cozic 2021-11-19 11:26:01 +00:00
parent c0b76cbd55
commit 0ec0d87e71
9 changed files with 128 additions and 49 deletions

View File

@ -1176,6 +1176,9 @@ packages/lib/models/utils/paginationToSql.js.map
packages/lib/models/utils/types.d.ts
packages/lib/models/utils/types.js
packages/lib/models/utils/types.js.map
packages/lib/net-utils.d.ts
packages/lib/net-utils.js
packages/lib/net-utils.js.map
packages/lib/ntp.d.ts
packages/lib/ntp.js
packages/lib/ntp.js.map

3
.gitignore vendored
View File

@ -1159,6 +1159,9 @@ packages/lib/models/utils/paginationToSql.js.map
packages/lib/models/utils/types.d.ts
packages/lib/models/utils/types.js
packages/lib/models/utils/types.js.map
packages/lib/net-utils.d.ts
packages/lib/net-utils.js
packages/lib/net-utils.js.map
packages/lib/ntp.d.ts
packages/lib/ntp.js
packages/lib/ntp.js.map

View File

@ -1,5 +1,5 @@
const Logger = require('@joplin/lib/Logger').default;
const { netUtils } = require('@joplin/lib/net-utils.js');
const { findAvailablePort } = require('@joplin/lib/net-utils');
const http = require('http');
const urlParser = require('url');
@ -36,7 +36,7 @@ class ResourceServer {
}
async start() {
this.port_ = await netUtils.findAvailablePort([9167, 9267, 8167, 8267]);
this.port_ = await findAvailablePort([9167, 9267, 8167, 8267]);
if (!this.port_) {
this.logger().error('Could not find available port to start resource server. Please report the error at https://github.com/laurent22/joplin');
return;

View File

@ -5,6 +5,7 @@ import JoplinError from './JoplinError';
import { Env } from './models/Setting';
import Logger from './Logger';
import personalizedUserContentBaseUrl from './services/joplinServer/personalizedUserContentBaseUrl';
import { getHttpStatusMessage } from './net-utils';
const { stringify } = require('query-string');
const logger = Logger.create('JoplinServerApi');
@ -245,7 +246,7 @@ export default class JoplinServerApi {
// <hr><center>nginx/1.18.0 (Ubuntu)</center>
// </body>
// </html>
throw newError(`Unknown error: ${shortResponseText()}`, response.status);
throw newError(`Error ${response.status} ${getHttpStatusMessage(response.status)}: ${shortResponseText()}`, response.status);
}
if (options.responseFormat === 'text') return responseText;

View File

@ -1,40 +0,0 @@
const shim = require('./shim').default;
const netUtils = {};
netUtils.ip = async () => {
const response = await shim.fetch('https://api.ipify.org/?format=json');
if (!response.ok) {
throw new Error(`Could not retrieve IP: ${await response.text()}`);
}
const ip = await response.json();
return ip.ip;
};
netUtils.findAvailablePort = async (possiblePorts, extraRandomPortsToTry = 20) => {
const tcpPortUsed = require('tcp-port-used');
for (let i = 0; i < extraRandomPortsToTry; i++) {
possiblePorts.push(Math.floor(8000 + Math.random() * 2000));
}
let port = null;
for (let i = 0; i < possiblePorts.length; i++) {
const inUse = await tcpPortUsed.check(possiblePorts[i]);
if (!inUse) {
port = possiblePorts[i];
break;
}
}
return port;
};
netUtils.mimeTypeFromHeaders = headers => {
if (!headers || !headers['content-type']) return null;
const splitted = headers['content-type'].split(';');
return splitted[0].trim().toLowerCase();
};
module.exports = { netUtils };

112
packages/lib/net-utils.ts Normal file
View File

@ -0,0 +1,112 @@
import shim from './shim';
export async function ip() {
const response = await shim.fetch('https://api.ipify.org/?format=json');
if (!response.ok) {
throw new Error(`Could not retrieve IP: ${await response.text()}`);
}
const ip = await response.json();
return ip.ip;
}
export async function findAvailablePort(possiblePorts: number[], extraRandomPortsToTry = 20) {
const tcpPortUsed = require('tcp-port-used');
for (let i = 0; i < extraRandomPortsToTry; i++) {
possiblePorts.push(Math.floor(8000 + Math.random() * 2000));
}
let port = null;
for (let i = 0; i < possiblePorts.length; i++) {
const inUse = await tcpPortUsed.check(possiblePorts[i]);
if (!inUse) {
port = possiblePorts[i];
break;
}
}
return port;
}
export async function mimeTypeFromHeaders(headers: Record<string, any>) {
if (!headers || !headers['content-type']) return null;
const splitted = headers['content-type'].split(';');
return splitted[0].trim().toLowerCase();
}
const httpStatusCodes_: Record<number, string> = {
100: 'Continue',
101: 'Switching Protocols',
102: 'Processing',
103: 'Early Hints',
200: 'OK',
201: 'Created',
202: 'Accepted',
203: 'Non-Authoritative Information',
204: 'No Content',
205: 'Reset Content',
206: 'Partial Content',
207: 'Multi-Status',
208: 'Already Reported',
226: 'IM Used',
300: 'Multiple Choices',
301: 'Moved Permanently',
302: 'Found',
303: 'See Other',
304: 'Not Modified',
305: 'Use Proxy',
307: 'Temporary Redirect',
308: 'Permanent Redirect',
400: 'Bad Request',
401: 'Unauthorized',
402: 'Payment Required',
403: 'Forbidden',
404: 'Not Found',
405: 'Method Not Allowed',
406: 'Not Acceptable',
407: 'Proxy Authentication Required',
408: 'Request Timeout',
409: 'Conflict',
410: 'Gone',
411: 'Length Required',
412: 'Precondition Failed',
413: 'Payload Too Large',
414: 'URI Too Long',
415: 'Unsupported Media Type',
416: 'Range Not Satisfiable',
417: 'Expectation Failed',
418: 'I\'m a Teapot',
421: 'Misdirected Request',
422: 'Unprocessable Entity',
423: 'Locked',
424: 'Failed Dependency',
425: 'Too Early',
426: 'Upgrade Required',
428: 'Precondition Required',
429: 'Too Many Requests',
431: 'Request Header Fields Too Large',
451: 'Unavailable For Legal Reasons',
500: 'Internal Server Error',
501: 'Not Implemented',
502: 'Bad Gateway',
503: 'Service Unavailable',
504: 'Gateway Timeout',
505: 'HTTP Version Not Supported',
506: 'Variant Also Negotiates',
507: 'Insufficient Storage',
508: 'Loop Detected',
509: 'Bandwidth Limit Exceeded',
510: 'Not Extended',
511: 'Network Authentication Required',
};
export function getHttpStatusMessage(statusCode: number): string {
const msg = httpStatusCodes_[statusCode];
// We don't throw an exception since a server can send any arbitrary error code
if (!msg) return 'Unknown status code';
return msg;
}

View File

@ -1,5 +1,5 @@
const { _ } = require('./locale');
const { netUtils } = require('./net-utils.js');
const { findAvailablePort } = require('./net-utils');
const shim = require('./shim').default;
const http = require('http');
@ -42,7 +42,7 @@ class OneDriveApiNodeUtils {
this.api().setAuth(null);
const port = await netUtils.findAvailablePort(this.possibleOAuthDancePorts(), 0);
const port = await findAvailablePort(this.possibleOAuthDancePorts(), 0);
if (!port) throw new Error(_('All potential ports are in use - please report the issue at %s', 'https://github.com/laurent22/joplin'));
const authCodeUrl = this.api().authCodeUrl(`http://localhost:${port}`);

View File

@ -23,7 +23,7 @@ const md5 = require('md5');
import HtmlToMd from '../../../HtmlToMd';
const urlUtils = require('../../../urlUtils.js');
const ArrayUtils = require('../../../ArrayUtils.js');
const { netUtils } = require('../../../net-utils');
const { mimeTypeFromHeaders } = require('../../../net-utils');
const { fileExtension, safeFileExtension, safeFilename, filename } = require('../../../path-utils');
const uri2path = require('file-uri-to-path');
const { MarkupToHtml } = require('@joplin/renderer');
@ -144,7 +144,7 @@ async function buildNoteStyleSheet(stylesheets: any[]) {
}
async function tryToGuessImageExtFromMimeType(response: any, imagePath: string) {
const mimeType = netUtils.mimeTypeFromHeaders(response.headers);
const mimeType = mimeTypeFromHeaders(response.headers);
if (!mimeType) return imagePath;
const newExt = mimeUtils.toFileExtension(mimeType);

View File

@ -8,7 +8,7 @@ const HtmlToMd = require('@joplin/lib/HtmlToMd').default;
const { dirname, filename, basename } = require('@joplin/lib/path-utils');
const markdownUtils = require('@joplin/lib/markdownUtils').default;
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
const { netUtils } = require('@joplin/lib/net-utils');
const { mimeTypeFromHeaders } = require('@joplin/lib/net-utils');
const shim = require('@joplin/lib/shim').default;
const moment = require('moment');
const { pregQuote } = require('@joplin/lib/string-utils');
@ -62,7 +62,7 @@ async function createPostFile(post, filePath) {
const imagePath = `${tempDir}/${imageFilename}`;
const response = await shim.fetchBlob(imageUrl, { path: imagePath, maxRetry: 1 });
const mimeType = netUtils.mimeTypeFromHeaders(response.headers);
const mimeType = mimeTypeFromHeaders(response.headers);
let ext = 'jpg';
if (mimeType) {
const newExt = mimeUtils.toFileExtension(mimeType);