const http = require('http'); /** * This is the default error handler to be used by this mock segment server. * It will print the error to the console and exit the process. * * @param {Error} error - The server error */ function defaultOnError(error) { console.log(error); process.exit(1); } /** * @typedef {import('http').IncomingMessage} IncomingMessage * @typedef {import('http').ServerResponse} ServerResponse */ /** * This function handles requests for the mock Segment server * * @typedef {(request: IncomingMessage, response: ServerResponse, metricEvents: Array) => void} MockSegmentRequestHandler */ /** * Creates a HTTP server that acts as a fake version of the Segment API. * The bevahiour is rudimentary at the moment - it returns HTTP 200 in response * to every request. The only function this serves is to spy on requests sent to * this server, and to parse the request payloads as Segment batch events. * * @param {MockSegmentRequestHandler} onRequest - A callback for each request the server receives. * @param {(error: Error) => void} [onError] - A callback for server error events */ function createSegmentServer(onRequest, onError = defaultOnError) { const server = http.createServer(async (request, response) => { const chunks = []; request.on('data', (chunk) => { chunks.push(chunk); }); await new Promise((resolve) => { request.on('end', () => { resolve(); }); }); // respond to preflight request if (request.method === 'OPTIONS') { response.setHeader('Access-Control-Allow-Origin', '*'); response.setHeader('Access-Control-Allow-Methods', '*'); response.setHeader('Access-Control-Allow-Headers', '*'); response.statusCode = 200; response.end(); return; } let metricEvents = []; if (chunks.length) { const body = Buffer.concat(chunks).toString(); const segmentPayload = JSON.parse(body); metricEvents = segmentPayload.batch; } onRequest(request, response, metricEvents); }); server.on('error', onError); return { start: async (port) => { await new Promise((resolve, reject) => { server.listen(port, (error) => { if (error) { return reject(error); } return resolve(); }); }); }, stop: async () => { await new Promise((resolve, reject) => { server.close((error) => { if (error) { return reject(error); } return resolve(); }); }); }, }; } module.exports = { createSegmentServer };