pref: 支持子域名托管的域名证书申请

This commit is contained in:
xiaojunnuo
2025-04-11 12:13:57 +08:00
parent f68af7dcf2
commit 67f956d4a0
21 changed files with 700 additions and 130 deletions
@@ -27,6 +27,7 @@ export type DnsProviderContext = {
logger: ILogger;
http: HttpClient;
utils: typeof utils;
domainParser: IDomainParser;
};
export interface IDnsProvider<T = any> {
@@ -35,3 +36,11 @@ export interface IDnsProvider<T = any> {
removeRecord(options: RemoveRecordOptions<T>): Promise<void>;
setCtx(ctx: DnsProviderContext): void;
}
export interface ISubDomainsGetter {
getSubDomains(): Promise<string[]>;
}
export interface IDomainParser {
parse(fullDomain: string): Promise<string>;
}
@@ -1,6 +1,4 @@
import { CreateRecordOptions, DnsProviderContext, DnsProviderDefine, IDnsProvider, RemoveRecordOptions } from "./api.js";
//@ts-ignore
import psl from "psl";
import { dnsProviderRegistry } from "./registry.js";
import { Decorator } from "@certd/pipeline";
import { HttpClient, ILogger } from "@certd/basic";
@@ -16,6 +14,10 @@ export abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
this.http = ctx.http;
}
async parseDomain(fullDomain: string) {
return await this.ctx.domainParser.parse(fullDomain);
}
abstract createRecord(options: CreateRecordOptions): Promise<T>;
abstract onInstance(): Promise<void>;
@@ -23,14 +25,6 @@ export abstract class AbstractDnsProvider<T = any> implements IDnsProvider<T> {
abstract removeRecord(options: RemoveRecordOptions<T>): Promise<void>;
}
export function parseDomain(fullDomain: string) {
const parsed = psl.parse(fullDomain) as psl.ParsedDomain;
if (parsed.error) {
throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
}
return parsed.domain as string;
}
export async function createDnsProvider(opts: { dnsProviderType: string; context: DnsProviderContext }): Promise<IDnsProvider> {
const { dnsProviderType, context } = opts;
const dnsProviderPlugin = dnsProviderRegistry.get(dnsProviderType);
@@ -0,0 +1,32 @@
import { IDomainParser, ISubDomainsGetter } from "./api";
//@ts-ignore
import psl from "psl";
export class DomainParser implements IDomainParser {
subDomainsGetter: ISubDomainsGetter;
constructor(subDomainsGetter: ISubDomainsGetter) {
this.subDomainsGetter = subDomainsGetter;
}
parseDomain(fullDomain: string) {
const parsed = psl.parse(fullDomain) as psl.ParsedDomain;
if (parsed.error) {
throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
}
return parsed.domain as string;
}
async parse(fullDomain: string) {
const subDomains = await this.subDomainsGetter.getSubDomains();
if (subDomains && subDomains.length > 0) {
for (const subDomain of subDomains) {
if (fullDomain.endsWith(subDomain)) {
//找到子域名托管
return subDomain;
}
}
}
return this.parseDomain(fullDomain);
}
}