n8n/packages/cli/src/controllers/telemetry.controller.ts
Ricardo Espinoza 5524b2137a
feat: Proxy all RudderStack frontend telemetry events through the backend (#17177)
Co-authored-by: Nikhil Kuriakose <nikhil.kuriakose@n8n.io>
2025-07-23 15:17:01 +02:00

60 lines
1.9 KiB
TypeScript

import { GlobalConfig } from '@n8n/config';
import { AuthenticatedRequest } from '@n8n/db';
import { Get, Post, RestController } from '@n8n/decorators';
import { NextFunction, Response } from 'express';
import { createProxyMiddleware, fixRequestBody } from 'http-proxy-middleware';
@RestController('/telemetry')
export class TelemetryController {
proxy;
constructor(private readonly globalConfig: GlobalConfig) {
this.proxy = createProxyMiddleware({
target: this.globalConfig.diagnostics.frontendConfig.split(';')[1],
changeOrigin: true,
pathRewrite: {
'^/proxy/': '/', // /proxy/v1/track -> /v1/track
},
on: {
proxyReq: (proxyReq, req) => {
proxyReq.removeHeader('cookie');
fixRequestBody(proxyReq, req);
return;
},
},
});
}
@Post('/proxy/:version/track', { skipAuth: true, rateLimit: { limit: 100, windowMs: 60_000 } })
async track(req: AuthenticatedRequest, res: Response, next: NextFunction) {
await this.proxy(req, res, next);
}
@Post('/proxy/:version/identify', { skipAuth: true, rateLimit: true })
async identify(req: AuthenticatedRequest, res: Response, next: NextFunction) {
await this.proxy(req, res, next);
}
@Post('/proxy/:version/page', { skipAuth: true, rateLimit: { limit: 50, windowMs: 60_000 } })
async page(req: AuthenticatedRequest, res: Response, next: NextFunction) {
await this.proxy(req, res, next);
}
@Get('/rudderstack/sourceConfig', { skipAuth: true, rateLimit: { limit: 50, windowMs: 60_000 } })
async sourceConfig() {
const response = await fetch('https://api-rs.n8n.io/sourceConfig', {
headers: {
authorization:
'Basic ' + btoa(`${this.globalConfig.diagnostics.frontendConfig.split(';')[0]}:`),
},
});
if (!response.ok) {
throw new Error(`Failed to fetch source config: ${response.statusText}`);
}
const config: unknown = await response.json();
return config;
}
}