You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	All: Resolves #5754: Improved error message when synchronising with Joplin Server
This commit is contained in:
		| @@ -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
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										112
									
								
								packages/lib/net-utils.ts
									
									
									
									
									
										Normal 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; | ||||
| } | ||||
| @@ -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}`); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user