@centinel/nextjs
Version:
Package designed to add Centinel Analytica functionality to Next.js applications
95 lines • 3.41 kB
JavaScript
class CentinelApiValidator {
config;
constructor(config) {
this.config = config;
}
async isBot(request) {
try {
const clientInfo = this.extractClientInfo(request);
const payload = this.buildValidationPayload(request, clientInfo);
const validationResult = await this.validateRequest(payload);
return (!validationResult.success ||
['block', 'redirect'].includes(validationResult.decision));
}
catch (error) {
console.error('Validation error:', error);
return false;
}
}
extractClientInfo(request) {
const forwardedFor = request.headers.get('x-forwarded-for');
const realIp = request.headers.get('x-real-ip');
const cfConnectingIp = request.headers.get('cf-connecting-ip');
return {
ip: cfConnectingIp ??
forwardedFor?.split(',')[0]?.trim() ??
realIp ??
'unknown',
referer: request.headers.get('referer') ?? request.headers.get('referrer') ?? '',
};
}
buildValidationPayload(request, clientInfo) {
const headers = {};
request.headers.forEach((value, key) => {
headers[key] = value;
});
let realHost = request.headers.get('x-forwarded-host') ??
request.headers.get('host') ??
request.nextUrl.hostname;
if (realHost === 'localhost' && !realHost.includes(':')) {
realHost = `localhost:${process.env.PORT ?? '3000'}`;
}
const requestUrl = `${request.nextUrl.protocol}//${realHost}${request.nextUrl.pathname}${request.nextUrl.search}`;
return {
cookie: request.cookies.get('_centinel')?.value,
url: requestUrl,
ip: clientInfo.ip,
referrer: clientInfo.referer,
method: request.method,
headers: headers,
};
}
async validateRequest(payload) {
try {
const response = await fetch('https://validator.centinelanalytica.com/validate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': this.config.secretKey,
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error(`Validator service responded with ${response.status}`);
}
const result = await response.json();
return {
success: result.success !== false,
decision: result.decision ?? 'block',
response_html: result.response_html,
cookies: result.cookies ?? [],
};
}
catch {
return {
success: false,
decision: 'block',
};
}
}
}
export function createRequestValidator(config) {
const validator = new CentinelApiValidator(config);
return {
isBot: (request) => validator.isBot(request),
};
}
export function createRequestValidatorFromEnv() {
const config = {
siteKey: process.env.CENTINEL_SITE_KEY,
secretKey: process.env.CENTINEL_SECRET_KEY,
};
return createRequestValidator(config);
}
export { CentinelApiValidator };
//# sourceMappingURL=api.js.map