feat(ssl): Add domain & certificate management, Cloudflare sync, SQLite cert manager, WebSocket realtime updates, and HTTP API SSL endpoints

This commit is contained in:
2025-11-18 19:34:26 +00:00
parent 44267bbb27
commit b94aa17eee
16 changed files with 1707 additions and 1344 deletions

View File

@@ -214,6 +214,16 @@ export class OneboxHttpServer {
} else if (path.match(/^\/api\/services\/[^/]+\/logs$/) && method === 'GET') {
const name = path.split('/')[3];
return await this.handleGetLogsRequest(name);
} else if (path === '/api/ssl/obtain' && method === 'POST') {
return await this.handleObtainCertificateRequest(req);
} else if (path === '/api/ssl/list' && method === 'GET') {
return await this.handleListCertificatesRequest();
} else if (path.match(/^\/api\/ssl\/[^/]+$/) && method === 'GET') {
const domain = path.split('/').pop()!;
return await this.handleGetCertificateRequest(domain);
} else if (path.match(/^\/api\/ssl\/[^/]+\/renew$/) && method === 'POST') {
const domain = path.split('/')[3];
return await this.handleRenewCertificateRequest(domain);
} else {
return this.jsonResponse({ success: false, error: 'Not found' }, 404);
}
@@ -442,6 +452,66 @@ export class OneboxHttpServer {
}
}
private async handleObtainCertificateRequest(req: Request): Promise<Response> {
try {
const body = await req.json();
const { domain, includeWildcard } = body;
if (!domain) {
return this.jsonResponse(
{ success: false, error: 'Domain is required' },
400
);
}
await this.oneboxRef.ssl.obtainCertificate(domain, includeWildcard || false);
return this.jsonResponse({
success: true,
message: `Certificate obtained for ${domain}`,
});
} catch (error) {
logger.error(`Failed to obtain certificate: ${error.message}`);
return this.jsonResponse({ success: false, error: error.message || 'Failed to obtain certificate' }, 500);
}
}
private async handleListCertificatesRequest(): Promise<Response> {
try {
const certificates = this.oneboxRef.ssl.listCertificates();
return this.jsonResponse({ success: true, data: certificates });
} catch (error) {
logger.error(`Failed to list certificates: ${error.message}`);
return this.jsonResponse({ success: false, error: error.message || 'Failed to list certificates' }, 500);
}
}
private async handleGetCertificateRequest(domain: string): Promise<Response> {
try {
const certificate = this.oneboxRef.ssl.getCertificate(domain);
if (!certificate) {
return this.jsonResponse({ success: false, error: 'Certificate not found' }, 404);
}
return this.jsonResponse({ success: true, data: certificate });
} catch (error) {
logger.error(`Failed to get certificate for ${domain}: ${error.message}`);
return this.jsonResponse({ success: false, error: error.message || 'Failed to get certificate' }, 500);
}
}
private async handleRenewCertificateRequest(domain: string): Promise<Response> {
try {
await this.oneboxRef.ssl.renewCertificate(domain);
return this.jsonResponse({
success: true,
message: `Certificate renewed for ${domain}`,
});
} catch (error) {
logger.error(`Failed to renew certificate for ${domain}: ${error.message}`);
return this.jsonResponse({ success: false, error: error.message || 'Failed to renew certificate' }, 500);
}
}
/**
* Handle WebSocket upgrade
*/