add logger and fix url preview
This commit is contained in:
parent
0f06a9ed0e
commit
0048f1538c
|
@ -9,6 +9,8 @@ import { StatusError } from '@/misc/status-error.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import * as undici from 'undici';
|
import * as undici from 'undici';
|
||||||
import { LookupFunction } from 'node:net';
|
import { LookupFunction } from 'node:net';
|
||||||
|
import { LoggerService } from '@/core/LoggerService.js';
|
||||||
|
import type Logger from '@/logger.js';
|
||||||
|
|
||||||
// true to allow, false to deny
|
// true to allow, false to deny
|
||||||
export type IpChecker = (ip: string) => boolean;
|
export type IpChecker = (ip: string) => boolean;
|
||||||
|
@ -32,7 +34,10 @@ export class UndiciFetcher {
|
||||||
private proxyBypassHosts: string[];
|
private proxyBypassHosts: string[];
|
||||||
private userAgent: string | undefined;
|
private userAgent: string | undefined;
|
||||||
|
|
||||||
constructor(args: {
|
private logger: Logger | undefined;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
args: {
|
||||||
agentOptions: undici.Agent.Options;
|
agentOptions: undici.Agent.Options;
|
||||||
proxy?: {
|
proxy?: {
|
||||||
uri: string;
|
uri: string;
|
||||||
|
@ -40,19 +45,50 @@ export class UndiciFetcher {
|
||||||
},
|
},
|
||||||
proxyBypassHosts?: string[];
|
proxyBypassHosts?: string[];
|
||||||
userAgent?: string;
|
userAgent?: string;
|
||||||
}) {
|
},
|
||||||
|
logger?: Logger,
|
||||||
|
) {
|
||||||
|
this.logger = logger;
|
||||||
|
this.logger?.debug('UndiciFetcher constructor', args);
|
||||||
|
|
||||||
this.proxyBypassHosts = args.proxyBypassHosts ?? [];
|
this.proxyBypassHosts = args.proxyBypassHosts ?? [];
|
||||||
this.userAgent = args.userAgent;
|
this.userAgent = args.userAgent;
|
||||||
|
|
||||||
this.nonProxiedAgent = new undici.Agent({
|
this.nonProxiedAgent = new undici.Agent({
|
||||||
...args.agentOptions,
|
...args.agentOptions,
|
||||||
|
connect: (process.env.NODE_ENV !== 'production' && typeof args.agentOptions.connect !== 'function')
|
||||||
|
? (options, cb) => {
|
||||||
|
undici.buildConnector(args.agentOptions.connect as undici.buildConnector.BuildOptions)(options, (err, socket) => {
|
||||||
|
if (err) {
|
||||||
|
this.logger?.debug(`Socket error`, err);
|
||||||
|
cb(new Error(`Error while socket connecting\n${err}`), null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.logger?.debug(`Socket connected: ${socket.localPort} => ${socket.remoteAddress}`);
|
||||||
|
cb(null, socket);
|
||||||
});
|
});
|
||||||
|
} : args.agentOptions.connect,
|
||||||
|
});
|
||||||
|
|
||||||
this.agent = args.proxy
|
this.agent = args.proxy
|
||||||
? new undici.ProxyAgent({
|
? new undici.ProxyAgent({
|
||||||
...args.agentOptions,
|
...args.agentOptions,
|
||||||
...args.proxy.options,
|
...args.proxy.options,
|
||||||
|
|
||||||
uri: args.proxy.uri,
|
uri: args.proxy.uri,
|
||||||
|
|
||||||
|
connect: (process.env.NODE_ENV !== 'production' && typeof (args.proxy?.options?.connect ?? args.agentOptions.connect) !== 'function')
|
||||||
|
? (options, cb) => {
|
||||||
|
undici.buildConnector((args.proxy?.options?.connect ?? args.agentOptions.connect) as undici.buildConnector.BuildOptions)(options, (err, socket) => {
|
||||||
|
if (err) {
|
||||||
|
this.logger?.debug(`Socket error`, err);
|
||||||
|
cb(new Error(`Error while socket connecting\n${err}`), null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.logger?.debug(`Socket connected: ${socket.localPort} => ${socket.remoteAddress}`);
|
||||||
|
cb(null, socket);
|
||||||
|
});
|
||||||
|
} : (args.proxy?.options?.connect ?? args.agentOptions.connect),
|
||||||
})
|
})
|
||||||
: this.nonProxiedAgent;
|
: this.nonProxiedAgent;
|
||||||
}
|
}
|
||||||
|
@ -144,10 +180,15 @@ export class HttpRequestService {
|
||||||
public readonly clientDefaults: undici.Agent.Options;
|
public readonly clientDefaults: undici.Agent.Options;
|
||||||
private maxSockets: number;
|
private maxSockets: number;
|
||||||
|
|
||||||
|
private logger: Logger;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.config)
|
@Inject(DI.config)
|
||||||
private config: Config,
|
private config: Config,
|
||||||
|
private loggerService: LoggerService,
|
||||||
) {
|
) {
|
||||||
|
this.logger = this.loggerService.getLogger('http-request');
|
||||||
|
|
||||||
this.dnsCache = new CacheableLookup({
|
this.dnsCache = new CacheableLookup({
|
||||||
maxTtl: 3600, // 1hours
|
maxTtl: 3600, // 1hours
|
||||||
errorTtl: 30, // 30secs
|
errorTtl: 30, // 30secs
|
||||||
|
@ -172,14 +213,14 @@ export class HttpRequestService {
|
||||||
|
|
||||||
this.maxSockets = Math.max(256, this.config.deliverJobConcurrency ?? 128);
|
this.maxSockets = Math.max(256, this.config.deliverJobConcurrency ?? 128);
|
||||||
|
|
||||||
this.defaultFetcher = new UndiciFetcher(this.getStandardUndiciFetcherConstructorOption());
|
this.defaultFetcher = new UndiciFetcher(this.getStandardUndiciFetcherConstructorOption(), this.logger);
|
||||||
|
|
||||||
this.fetch = this.defaultFetcher.fetch;
|
this.fetch = this.defaultFetcher.fetch;
|
||||||
this.getHtml = this.defaultFetcher.getHtml;
|
this.getHtml = this.defaultFetcher.getHtml;
|
||||||
|
|
||||||
this.defaultJsonFetcher = new UndiciFetcher(this.getStandardUndiciFetcherConstructorOption({
|
this.defaultJsonFetcher = new UndiciFetcher(this.getStandardUndiciFetcherConstructorOption({
|
||||||
maxResponseSize: 1024 * 256,
|
maxResponseSize: 1024 * 256,
|
||||||
}));
|
}), this.logger);
|
||||||
|
|
||||||
this.getJson = this.defaultJsonFetcher.getJson;
|
this.getJson = this.defaultJsonFetcher.getJson;
|
||||||
|
|
||||||
|
@ -263,25 +304,30 @@ export class HttpRequestService {
|
||||||
@bindThis
|
@bindThis
|
||||||
public getConnectorWithIpCheck(connector: undici.buildConnector.connector, checkIp: IpChecker): undici.buildConnector.connectorAsync {
|
public getConnectorWithIpCheck(connector: undici.buildConnector.connector, checkIp: IpChecker): undici.buildConnector.connectorAsync {
|
||||||
return (options, cb) => {
|
return (options, cb) => {
|
||||||
|
this.logger.debug('socket connecting...')
|
||||||
connector(options, (err, socket) => {
|
connector(options, (err, socket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
cb(err, null);
|
this.logger.error(`Socket error`, err)
|
||||||
|
cb(new Error(`Error while socket connecting\n${err}`), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socket.remoteAddress == undefined) {
|
if (socket.remoteAddress == undefined) {
|
||||||
|
this.logger.error(`Socket error: remoteAddress is undefined`);
|
||||||
cb(new Error('remoteAddress is undefined (maybe socket destroyed)'), null);
|
cb(new Error('remoteAddress is undefined (maybe socket destroyed)'), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow
|
// allow
|
||||||
if (checkIp(socket.remoteAddress)) {
|
if (checkIp(socket.remoteAddress)) {
|
||||||
|
this.logger.debug(`Socket connected (ip ok): ${socket.localPort} => ${socket.remoteAddress}`);
|
||||||
cb(null, socket);
|
cb(null, socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.destroy();
|
this.logger.error('IP is not allowed', socket);
|
||||||
cb(new StatusError('IP is not allowed', 403, 'IP is not allowed'), null);
|
cb(new StatusError('IP is not allowed', 403, 'IP is not allowed'), null);
|
||||||
|
socket.destroy();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import * as summaly from 'summaly';
|
import summaly from 'summaly';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { UsersRepository } from '@/models/index.js';
|
import type { UsersRepository } from '@/models/index.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
|
|
Loading…
Reference in New Issue