JavaScript 构建一棵 DNS 树

背景

在开发帕秋莉(基于 OpenResty & Node.js 的网关系统)时,需要解析域名并转发请求到真实业务服务器上去,帕秋莉支持 *.xxx.com 这样的通配域名,所以涉及到解析包含层级关系的子域名。

思路

实现一棵树,树的每个节点存储域名对应的信息,子节点存储子域名对应的信息。

节点

字段类型含义示例
idStringID0pzPEiCTR1V
valueString域名*.xxx.com
isWildcardBool是否为通配域名true
accessControlAllowOriginString允许跨域的域名*
appIdString业务服务器 IDbEYO9iCTRoM
regexpString域名正则表达式/^((?:.*)).xxx.com(?:/(?=))?/i
childrenArray子节点

代码

实现

class DNS {
    constructor(domain) {
        // 节点
        this.id = domain.id;
        this.value = domain.value;
        this.isWildcard = domain.isWildcard;
        this.accessControlAllowOrigin = domain.accessControlAllowOrigin;
        this.appId = domain.appId;

        this.regexp = pathToRegexp(domain.value);
        this.children = [];
    }

    init(domain) {
        // 新节点与当前节点不存在主子关系
        if(!this.regexp.exec(domain.value)) return false;

        // 尝试向当前节点的所有自己点添加新节点
        let result = false;
        for(const child of this.children) {
            result = child.init(domain);
            if(result) break;
        }
        // 添加失败新节点是当前子节点的兄弟节点
        if(!result) {
            this.children.push(domain);
            result = true;
        }
        return result;
    }

    parse(domain) {
        // 需要解析的节点与当前节点不存在包含关系
        if(!this.regexp.exec(domain.value)) return null;

        // 尝试在当前节点的所有自己点中解析
        let result = null;
        for(const child of this.children) {
            result = child.parse(domain);
            if(result) break;
        }
        // 解析失败代表需要解析的节点不存在与当前节点的子节点中
        // 满足当前节点的正则,不满足当前节点所有子节点的正则,需要解析的节点即为当前节点
        if(!result) {
            result = {
                id: this.id,
                value: this.value,
                isWildcard: this.isWildcard,
                accessControlAllowOrigin: this.accessControlAllowOrigin,
                appId: this.appId,
                regexp: this.regexp,
                children: this.children
            };
        }
        return result;
    }
}
复制代码

使用

// 使用 * 创建一个 root 节点
const dns = new DNS({ value: * });
dns.init({
    id: '0pzPEiCTR1V',
    value: '*.xxx.com',
    isWildcard: true,
    accessControlAllowOrigin: '*',
    appId: bEYO9iCTRoM
});

// 利用域名解析节点详细信息
const result = dns.parse({
    value: '*.xxx.com'
});
console.log(result);
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值