icydns/src/interceptors/domain.interceptor.ts

68 lines
1.9 KiB
TypeScript

import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
HttpException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Request, Response } from 'express';
import { resolve } from 'path';
import { from, Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { DNSCacheService } from 'src/modules/objects/dns/dns-cache.service';
import { ManagerService } from 'src/modules/objects/manager/manager.service';
import { CachedZone } from 'src/types/dns.interfaces';
@Injectable()
export class DomainInterceptor implements NestInterceptor {
constructor(
private dns: DNSCacheService,
private manage: ManagerService,
private config: ConfigService,
) {}
async getOrLoad(domain: string): Promise<CachedZone> {
if (!this.dns.has(domain)) {
const exists = await this.manage.getZone(domain);
if (!exists) throw new HttpException('No such zonefile', 404);
return this.dns.load(
domain,
resolve(
process.cwd(),
this.config.get<string>('zoneDir'),
`${domain}.zone`,
),
);
}
const get = await this.dns.get(domain);
if (!get) {
throw new HttpException('Misconfigured domain zone file.', 400);
}
return get;
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest<Request>();
const response = context.switchToHttp().getResponse<Response>();
let base = of(null);
const domain = request.params.domain;
if (domain) {
base = from(
(async () => {
const domainCache = await this.getOrLoad(domain);
response.locals.domain = domain;
response.locals.cached = domainCache;
return null;
})(),
);
}
return base.pipe(switchMap(() => next.handle()));
}
}