feat: Update error handling to use getErrorMessage utility and improve logging across multiple services
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
"@std/encoding": "jsr:@std/encoding@^1.0.10",
|
||||
"@db/sqlite": "jsr:@db/sqlite@0.12.0",
|
||||
"@push.rocks/smartdaemon": "npm:@push.rocks/smartdaemon@^2.1.0",
|
||||
"@apiclient.xyz/docker": "npm:@apiclient.xyz/docker@^5.0.2",
|
||||
"@apiclient.xyz/docker": "npm:@apiclient.xyz/docker@^5.1.0",
|
||||
"@apiclient.xyz/cloudflare": "npm:@apiclient.xyz/cloudflare@6.4.3",
|
||||
"@push.rocks/smartacme": "npm:@push.rocks/smartacme@^8.0.0",
|
||||
"@push.rocks/smartregistry": "npm:@push.rocks/smartregistry@^1.8.0",
|
||||
|
||||
5
mod.ts
5
mod.ts
@@ -7,13 +7,14 @@
|
||||
*/
|
||||
|
||||
import { runCli } from './ts/index.ts';
|
||||
import { getErrorMessage } from './ts/utils/error.ts';
|
||||
|
||||
if (import.meta.main) {
|
||||
try {
|
||||
await runCli();
|
||||
} catch (error) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
if (Deno.args.includes('--debug')) {
|
||||
console.error(`Error: ${getErrorMessage(error)}`);
|
||||
if (Deno.args.includes('--debug') && error instanceof Error) {
|
||||
console.error(error.stack);
|
||||
}
|
||||
Deno.exit(1);
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
ISslCertificate,
|
||||
IServiceDeployOptions,
|
||||
} from '../types.ts';
|
||||
import { getErrorMessage } from '../utils/error.ts';
|
||||
|
||||
export class OneboxApiClient {
|
||||
private baseUrl: string;
|
||||
@@ -193,7 +194,7 @@ export class OneboxApiClient {
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
if (error.name === 'TimeoutError') {
|
||||
if (error instanceof Error && error.name === 'TimeoutError') {
|
||||
throw new Error('Request timed out. Daemon might be unresponsive.');
|
||||
}
|
||||
throw error;
|
||||
|
||||
@@ -836,7 +836,7 @@ export class OneboxDatabase {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
const values: BindValue[] = [];
|
||||
|
||||
if (updates.image !== undefined) {
|
||||
fields.push('image = ?');
|
||||
@@ -1202,7 +1202,7 @@ export class OneboxDatabase {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
const values: BindValue[] = [];
|
||||
|
||||
if (updates.certPath) {
|
||||
fields.push('cert_path = ?');
|
||||
@@ -1303,7 +1303,7 @@ export class OneboxDatabase {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
const values: BindValue[] = [];
|
||||
|
||||
if (updates.domain !== undefined) {
|
||||
fields.push('domain = ?');
|
||||
@@ -1405,7 +1405,7 @@ export class OneboxDatabase {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
const values: BindValue[] = [];
|
||||
|
||||
if (updates.certDomain !== undefined) {
|
||||
fields.push('cert_domain = ?');
|
||||
@@ -1524,7 +1524,7 @@ export class OneboxDatabase {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
const values: BindValue[] = [];
|
||||
|
||||
if (updates.subdomain !== undefined) {
|
||||
fields.push('subdomain = ?');
|
||||
@@ -1711,7 +1711,7 @@ export class OneboxDatabase {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
const values: BindValue[] = [];
|
||||
|
||||
if (updates.status !== undefined) {
|
||||
fields.push('status = ?');
|
||||
|
||||
@@ -10,7 +10,7 @@ import { logger } from '../logging.ts';
|
||||
import { getErrorMessage } from '../utils/error.ts';
|
||||
|
||||
export class OneboxDockerManager {
|
||||
private dockerClient: plugins.docker.Docker | null = null;
|
||||
private dockerClient: InstanceType<typeof plugins.docker.Docker> | null = null;
|
||||
private networkName = 'onebox-network';
|
||||
|
||||
/**
|
||||
@@ -695,14 +695,6 @@ export class OneboxDockerManager {
|
||||
timestamps: true,
|
||||
});
|
||||
|
||||
// v5 should return a string, but let's handle edge cases
|
||||
if (typeof logs !== 'string') {
|
||||
logger.error(`Unexpected logs type: ${typeof logs}, constructor: ${logs?.constructor?.name}`);
|
||||
logger.error(`Logs content: ${JSON.stringify(logs).slice(0, 500)}`);
|
||||
// If it's not a string, something went wrong
|
||||
throw new Error(`Unexpected log format: expected string, got ${typeof logs}`);
|
||||
}
|
||||
|
||||
// v5 returns already-parsed logs as a string
|
||||
return {
|
||||
stdout: logs,
|
||||
@@ -809,20 +801,17 @@ export class OneboxDockerManager {
|
||||
throw new Error(`Container not found: ${containerID}`);
|
||||
}
|
||||
|
||||
const exec = await container.exec({
|
||||
Cmd: cmd,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
const { stream, inspect } = await container.exec(cmd, {
|
||||
attachStdout: true,
|
||||
attachStderr: true,
|
||||
});
|
||||
|
||||
const stream = await exec.start({ Detach: false });
|
||||
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
|
||||
stream.on('data', (chunk: Buffer) => {
|
||||
stream.on('data', (chunk: Uint8Array) => {
|
||||
const streamType = chunk[0];
|
||||
const content = chunk.slice(8).toString();
|
||||
const content = new TextDecoder().decode(chunk.slice(8));
|
||||
|
||||
if (streamType === 1) {
|
||||
stdout += content;
|
||||
@@ -834,8 +823,8 @@ export class OneboxDockerManager {
|
||||
// Wait for completion
|
||||
await new Promise((resolve) => stream.on('end', resolve));
|
||||
|
||||
const inspect = await exec.inspect();
|
||||
const exitCode = inspect.ExitCode || 0;
|
||||
const execInfo = await inspect();
|
||||
const exitCode = execInfo.ExitCode || 0;
|
||||
|
||||
return { stdout, stderr, exitCode };
|
||||
} catch (error) {
|
||||
@@ -928,4 +917,26 @@ export class OneboxDockerManager {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a container by ID
|
||||
* Public wrapper for Docker client method
|
||||
*/
|
||||
async getContainerById(containerID: string): Promise<any> {
|
||||
if (!this.dockerClient) {
|
||||
throw new Error('Docker client not initialized');
|
||||
}
|
||||
return this.dockerClient.getContainerById(containerID);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all containers
|
||||
* Public wrapper for Docker client method
|
||||
*/
|
||||
async listAllContainers(): Promise<any[]> {
|
||||
if (!this.dockerClient) {
|
||||
throw new Error('Docker client not initialized');
|
||||
}
|
||||
return this.dockerClient.listContainers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export class CredentialEncryption {
|
||||
}
|
||||
this.key = await crypto.subtle.importKey(
|
||||
'raw',
|
||||
keyBytes,
|
||||
keyBytes.buffer as ArrayBuffer,
|
||||
{ name: this.algorithm },
|
||||
false,
|
||||
['encrypt', 'decrypt']
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as plugins from '../plugins.ts';
|
||||
import { logger } from '../logging.ts';
|
||||
import { getErrorMessage } from '../utils/error.ts';
|
||||
import type { Onebox } from './onebox.ts';
|
||||
import type { IApiResponse, ICreateRegistryTokenRequest, IRegistryTokenView } from '../types.ts';
|
||||
import type { IApiResponse, ICreateRegistryTokenRequest, IRegistryTokenView, TPlatformServiceType } from '../types.ts';
|
||||
|
||||
export class OneboxHttpServer {
|
||||
private oneboxRef: Onebox;
|
||||
@@ -482,8 +482,8 @@ export class OneboxHttpServer {
|
||||
private async handleGetLogsRequest(name: string): Promise<Response> {
|
||||
try {
|
||||
const logs = await this.oneboxRef.services.getServiceLogs(name);
|
||||
logger.log(`handleGetLogsRequest: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`);
|
||||
logger.log(`handleGetLogsRequest: logs value = ${String(logs).slice(0, 100)}`);
|
||||
logger.debug(`handleGetLogsRequest: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`);
|
||||
logger.debug(`handleGetLogsRequest: logs value = ${String(logs).slice(0, 100)}`);
|
||||
return this.jsonResponse({ success: true, data: logs });
|
||||
} catch (error) {
|
||||
logger.error(`Failed to get logs for service ${name}: ${getErrorMessage(error)}`);
|
||||
@@ -878,13 +878,13 @@ export class OneboxHttpServer {
|
||||
|
||||
// Get the container (handle both direct container IDs and service IDs)
|
||||
logger.info(`Looking up container for service ${serviceName}, containerID: ${service.containerID}`);
|
||||
let container = await this.oneboxRef.docker.dockerClient!.getContainerById(service.containerID!);
|
||||
let container = await this.oneboxRef.docker.getContainerById(service.containerID!);
|
||||
logger.info(`Direct lookup result: ${container ? 'found' : 'null'}`);
|
||||
|
||||
// If not found, it might be a service ID - try to get the actual container ID
|
||||
if (!container) {
|
||||
logger.info('Listing all containers to find matching service...');
|
||||
const containers = await this.oneboxRef.docker.dockerClient!.listContainers();
|
||||
const containers = await this.oneboxRef.docker.listAllContainers();
|
||||
logger.info(`Found ${containers.length} containers`);
|
||||
|
||||
const serviceContainer = containers.find((c: any) => {
|
||||
@@ -894,7 +894,7 @@ export class OneboxHttpServer {
|
||||
|
||||
if (serviceContainer) {
|
||||
logger.info(`Found matching container: ${serviceContainer.Id}`);
|
||||
container = await this.oneboxRef.docker.dockerClient!.getContainerById(serviceContainer.Id);
|
||||
container = await this.oneboxRef.docker.getContainerById(serviceContainer.Id);
|
||||
logger.info(`Second lookup result: ${container ? 'found' : 'null'}`);
|
||||
} else {
|
||||
logger.error(`No container found with service label matching ${service.containerID}`);
|
||||
@@ -924,18 +924,21 @@ export class OneboxHttpServer {
|
||||
|
||||
// Demultiplex and pipe log data to WebSocket
|
||||
// Docker streams use 8-byte headers: [STREAM_TYPE, 0, 0, 0, SIZE_BYTE1, SIZE_BYTE2, SIZE_BYTE3, SIZE_BYTE4]
|
||||
let buffer = Buffer.alloc(0);
|
||||
let buffer = new Uint8Array(0);
|
||||
|
||||
logStream.on('data', (chunk: Buffer) => {
|
||||
logStream.on('data', (chunk: Uint8Array) => {
|
||||
if (socket.readyState !== WebSocket.OPEN) return;
|
||||
|
||||
// Append new data to buffer
|
||||
buffer = Buffer.concat([buffer, chunk]);
|
||||
const newBuffer = new Uint8Array(buffer.length + chunk.length);
|
||||
newBuffer.set(buffer);
|
||||
newBuffer.set(chunk, buffer.length);
|
||||
buffer = newBuffer;
|
||||
|
||||
// Process complete frames
|
||||
while (buffer.length >= 8) {
|
||||
// Read frame size from header (bytes 4-7, big-endian)
|
||||
const frameSize = buffer.readUInt32BE(4);
|
||||
const frameSize = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
|
||||
|
||||
// Check if we have the complete frame
|
||||
if (buffer.length < 8 + frameSize) {
|
||||
@@ -946,7 +949,7 @@ export class OneboxHttpServer {
|
||||
const frameData = buffer.slice(8, 8 + frameSize);
|
||||
|
||||
// Send the clean log line
|
||||
socket.send(frameData.toString('utf8'));
|
||||
socket.send(new TextDecoder().decode(frameData));
|
||||
|
||||
// Remove processed frame from buffer
|
||||
buffer = buffer.slice(8 + frameSize);
|
||||
@@ -1083,7 +1086,7 @@ export class OneboxHttpServer {
|
||||
}
|
||||
}
|
||||
|
||||
private async handleGetPlatformServiceRequest(type: string): Promise<Response> {
|
||||
private async handleGetPlatformServiceRequest(type: TPlatformServiceType): Promise<Response> {
|
||||
try {
|
||||
const provider = this.oneboxRef.platformServices.getProvider(type);
|
||||
if (!provider) {
|
||||
@@ -1123,7 +1126,7 @@ export class OneboxHttpServer {
|
||||
}
|
||||
}
|
||||
|
||||
private async handleStartPlatformServiceRequest(type: string): Promise<Response> {
|
||||
private async handleStartPlatformServiceRequest(type: TPlatformServiceType): Promise<Response> {
|
||||
try {
|
||||
const provider = this.oneboxRef.platformServices.getProvider(type);
|
||||
if (!provider) {
|
||||
@@ -1154,7 +1157,7 @@ export class OneboxHttpServer {
|
||||
}
|
||||
}
|
||||
|
||||
private async handleStopPlatformServiceRequest(type: string): Promise<Response> {
|
||||
private async handleStopPlatformServiceRequest(type: TPlatformServiceType): Promise<Response> {
|
||||
try {
|
||||
const provider = this.oneboxRef.platformServices.getProvider(type);
|
||||
if (!provider) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import type { IPlatformServiceProvider } from './providers/base.ts';
|
||||
import { MongoDBProvider } from './providers/mongodb.ts';
|
||||
import { MinioProvider } from './providers/minio.ts';
|
||||
import { logger } from '../../logging.ts';
|
||||
import { getErrorMessage } from '../../utils/error.ts';
|
||||
import { credentialEncryption } from '../encryption.ts';
|
||||
import type { Onebox } from '../onebox.ts';
|
||||
|
||||
@@ -126,7 +127,7 @@ export class PlatformServicesManager {
|
||||
// Refresh platform service from database
|
||||
platformService = this.oneboxRef.database.getPlatformServiceByType(type)!;
|
||||
} catch (error) {
|
||||
logger.error(`Failed to start ${provider.displayName}: ${error.message}`);
|
||||
logger.error(`Failed to start ${provider.displayName}: ${getErrorMessage(error)}`);
|
||||
this.oneboxRef.database.updatePlatformService(platformService.id!, { status: 'failed' });
|
||||
throw error;
|
||||
}
|
||||
@@ -187,7 +188,7 @@ export class PlatformServicesManager {
|
||||
});
|
||||
logger.success(`${provider.displayName} platform service stopped`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to stop ${provider.displayName}: ${error.message}`);
|
||||
logger.error(`Failed to stop ${provider.displayName}: ${getErrorMessage(error)}`);
|
||||
this.oneboxRef.database.updatePlatformService(platformService.id!, { status: 'failed' });
|
||||
throw error;
|
||||
}
|
||||
@@ -292,7 +293,7 @@ export class PlatformServicesManager {
|
||||
this.oneboxRef.database.deletePlatformResource(resource.id!);
|
||||
logger.success(`Cleaned up ${resource.resourceType} '${resource.resourceName}'`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to cleanup resource ${resource.id}: ${error.message}`);
|
||||
logger.error(`Failed to cleanup resource ${resource.id}: ${getErrorMessage(error)}`);
|
||||
// Continue with other resources even if one fails
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import type {
|
||||
TPlatformResourceType,
|
||||
} from '../../../types.ts';
|
||||
import { logger } from '../../../logging.ts';
|
||||
import { getErrorMessage } from '../../../utils/error.ts';
|
||||
import { credentialEncryption } from '../../encryption.ts';
|
||||
import type { Onebox } from '../../onebox.ts';
|
||||
|
||||
@@ -73,7 +74,7 @@ export class MinioProvider extends BasePlatformServiceProvider {
|
||||
await Deno.mkdir('/var/lib/onebox/minio', { recursive: true });
|
||||
} catch (e) {
|
||||
if (!(e instanceof Deno.errors.AlreadyExists)) {
|
||||
logger.warn(`Could not create MinIO data directory: ${e.message}`);
|
||||
logger.warn(`Could not create MinIO data directory: ${getErrorMessage(e)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ export class MinioProvider extends BasePlatformServiceProvider {
|
||||
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
logger.debug(`MinIO health check failed: ${error.message}`);
|
||||
logger.debug(`MinIO health check failed: ${getErrorMessage(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +206,7 @@ export class MinioProvider extends BasePlatformServiceProvider {
|
||||
}));
|
||||
logger.info(`Set bucket policy for '${bucketName}'`);
|
||||
} catch (e) {
|
||||
logger.warn(`Could not set bucket policy: ${e.message}`);
|
||||
logger.warn(`Could not set bucket policy: ${getErrorMessage(e)}`);
|
||||
}
|
||||
|
||||
// Note: For proper per-service credentials, MinIO Admin API should be used
|
||||
@@ -292,7 +293,7 @@ export class MinioProvider extends BasePlatformServiceProvider {
|
||||
|
||||
logger.success(`MinIO bucket '${resource.resourceName}' deleted`);
|
||||
} catch (e) {
|
||||
logger.error(`Failed to delete MinIO bucket: ${e.message}`);
|
||||
logger.error(`Failed to delete MinIO bucket: ${getErrorMessage(e)}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import type {
|
||||
TPlatformResourceType,
|
||||
} from '../../../types.ts';
|
||||
import { logger } from '../../../logging.ts';
|
||||
import { getErrorMessage } from '../../../utils/error.ts';
|
||||
import { credentialEncryption } from '../../encryption.ts';
|
||||
import type { Onebox } from '../../onebox.ts';
|
||||
|
||||
@@ -69,7 +70,7 @@ export class MongoDBProvider extends BasePlatformServiceProvider {
|
||||
} catch (e) {
|
||||
// Directory might already exist
|
||||
if (!(e instanceof Deno.errors.AlreadyExists)) {
|
||||
logger.warn(`Could not create MongoDB data directory: ${e.message}`);
|
||||
logger.warn(`Could not create MongoDB data directory: ${getErrorMessage(e)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +136,7 @@ export class MongoDBProvider extends BasePlatformServiceProvider {
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.debug(`MongoDB health check failed: ${error.message}`);
|
||||
logger.debug(`MongoDB health check failed: ${getErrorMessage(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +234,7 @@ export class MongoDBProvider extends BasePlatformServiceProvider {
|
||||
await db.command({ dropUser: credentials.username });
|
||||
logger.info(`Dropped MongoDB user '${credentials.username}'`);
|
||||
} catch (e) {
|
||||
logger.warn(`Could not drop MongoDB user: ${e.message}`);
|
||||
logger.warn(`Could not drop MongoDB user: ${getErrorMessage(e)}`);
|
||||
}
|
||||
|
||||
// Drop the database
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import * as plugins from '../plugins.ts';
|
||||
import { logger } from '../logging.ts';
|
||||
import { getErrorMessage } from '../utils/error.ts';
|
||||
|
||||
export class RegistryManager {
|
||||
private s3Server: any = null;
|
||||
@@ -86,7 +87,7 @@ export class RegistryManager {
|
||||
this.isInitialized = true;
|
||||
logger.success('Onebox Registry initialized successfully');
|
||||
} catch (error) {
|
||||
logger.error(`Failed to initialize registry: ${error.message}`);
|
||||
logger.error(`Failed to initialize registry: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -102,7 +103,7 @@ export class RegistryManager {
|
||||
try {
|
||||
return await this.registry.handleRequest(req);
|
||||
} catch (error) {
|
||||
logger.error(`Registry request error: ${error.message}`);
|
||||
logger.error(`Registry request error: ${getErrorMessage(error)}`);
|
||||
return new Response('Internal registry error', { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -119,7 +120,7 @@ export class RegistryManager {
|
||||
const tags = await this.registry.getTags(repository);
|
||||
return tags || [];
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to get tags for ${repository}: ${error.message}`);
|
||||
logger.warn(`Failed to get tags for ${repository}: ${getErrorMessage(error)}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -146,8 +147,9 @@ export class RegistryManager {
|
||||
return null;
|
||||
} catch (error) {
|
||||
// Only log if it's not a "not a function" error
|
||||
if (!error.message.includes('not a function')) {
|
||||
logger.warn(`Failed to get digest for ${repository}:${tag}: ${error.message}`);
|
||||
const errMsg = getErrorMessage(error);
|
||||
if (!errMsg.includes('not a function')) {
|
||||
logger.warn(`Failed to get digest for ${repository}:${tag}: ${errMsg}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -165,7 +167,7 @@ export class RegistryManager {
|
||||
await this.registry.deleteManifest(repository, tag);
|
||||
logger.info(`Deleted image ${repository}:${tag}`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to delete image ${repository}:${tag}: ${error.message}`);
|
||||
logger.error(`Failed to delete image ${repository}:${tag}: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -212,7 +214,7 @@ export class RegistryManager {
|
||||
await this.s3Server.stop();
|
||||
logger.info('smarts3 server stopped');
|
||||
} catch (error) {
|
||||
logger.error(`Error stopping smarts3: ${error.message}`);
|
||||
logger.error(`Error stopping smarts3: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import { logger } from '../logging.ts';
|
||||
import { getErrorMessage } from '../utils/error.ts';
|
||||
import { OneboxDatabase } from './database.ts';
|
||||
|
||||
interface IProxyRoute {
|
||||
@@ -43,7 +44,7 @@ export class OneboxReverseProxy {
|
||||
try {
|
||||
logger.info('Reverse proxy initialized');
|
||||
} catch (error) {
|
||||
logger.error(`Failed to initialize reverse proxy: ${error.message}`);
|
||||
logger.error(`Failed to initialize reverse proxy: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -77,7 +78,7 @@ export class OneboxReverseProxy {
|
||||
|
||||
logger.success(`HTTP reverse proxy started on port ${this.httpPort}`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to start HTTP reverse proxy: ${error.message}`);
|
||||
logger.error(`Failed to start HTTP reverse proxy: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -122,7 +123,7 @@ export class OneboxReverseProxy {
|
||||
|
||||
logger.success(`HTTPS reverse proxy started on port ${this.httpsPort}`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to start HTTPS reverse proxy: ${error.message}`);
|
||||
logger.error(`Failed to start HTTPS reverse proxy: ${getErrorMessage(error)}`);
|
||||
// Don't throw - HTTPS is optional
|
||||
logger.warn('Continuing without HTTPS support');
|
||||
}
|
||||
@@ -197,7 +198,7 @@ export class OneboxReverseProxy {
|
||||
headers: this.filterResponseHeaders(response.headers),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(`Proxy error for ${host}: ${error.message}`);
|
||||
logger.error(`Proxy error for ${host}: ${getErrorMessage(error)}`);
|
||||
return new Response('Bad Gateway', {
|
||||
status: 502,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
@@ -264,7 +265,7 @@ export class OneboxReverseProxy {
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
logger.error(`WebSocket upgrade error: ${error.message}`);
|
||||
logger.error(`WebSocket upgrade error: ${getErrorMessage(error)}`);
|
||||
return new Response('WebSocket Upgrade Failed', {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
@@ -353,7 +354,7 @@ export class OneboxReverseProxy {
|
||||
this.routes.set(domain, route);
|
||||
logger.success(`Added proxy route: ${domain} -> ${targetHost}:${targetPort}`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to add route for ${domain}: ${error.message}`);
|
||||
logger.error(`Failed to add route for ${domain}: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -395,7 +396,7 @@ export class OneboxReverseProxy {
|
||||
|
||||
logger.success(`Loaded ${this.routes.size} proxy routes`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to reload routes: ${error.message}`);
|
||||
logger.error(`Failed to reload routes: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -423,7 +424,7 @@ export class OneboxReverseProxy {
|
||||
logger.warn('HTTPS server restart required for new certificate to take effect');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Failed to add certificate for ${domain}: ${error.message}`);
|
||||
logger.error(`Failed to add certificate for ${domain}: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -455,7 +456,7 @@ export class OneboxReverseProxy {
|
||||
try {
|
||||
await this.addCertificate(cert.domain, cert.fullChainPath, cert.keyPath);
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to load certificate for ${cert.domain}: ${error.message}`);
|
||||
logger.warn(`Failed to load certificate for ${cert.domain}: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,7 +471,7 @@ export class OneboxReverseProxy {
|
||||
await this.startHttps();
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Failed to reload certificates: ${error.message}`);
|
||||
logger.error(`Failed to reload certificates: ${getErrorMessage(error)}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,9 +382,9 @@ export class OneboxServicesManager {
|
||||
const logs = await this.docker.getContainerLogs(service.containerID, tail);
|
||||
|
||||
// Debug: check what we got
|
||||
logger.log(`getServiceLogs: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`);
|
||||
logger.log(`getServiceLogs: logs.stdout type = ${typeof logs.stdout}`);
|
||||
logger.log(`getServiceLogs: logs.stdout value = ${String(logs.stdout).slice(0, 100)}`);
|
||||
logger.debug(`getServiceLogs: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`);
|
||||
logger.debug(`getServiceLogs: logs.stdout type = ${typeof logs.stdout}`);
|
||||
logger.debug(`getServiceLogs: logs.stdout value = ${String(logs.stdout).slice(0, 100)}`);
|
||||
|
||||
// v5 API returns combined stdout/stderr with proper formatting
|
||||
return logs.stdout;
|
||||
@@ -746,7 +746,7 @@ export class OneboxServicesManager {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Failed to check updates for ${service.name}: ${error.message}`);
|
||||
logger.error(`Failed to check updates for ${service.name}: ${getErrorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user