openreplay/assist/utils/httpHandlers.js

217 lines
No EOL
6.9 KiB
JavaScript

const {
hasFilters,
hasQuery,
isValidSession,
sortPaginate,
getValidAttributes,
uniqueAutocomplete
} = require("./helper");
const {
extractProjectKeyFromRequest,
extractSessionIdFromRequest,
extractPayloadFromRequest,
} = require("./extractors");
const {
RecordRequestDuration,
IncreaseTotalRequests
} = require('../utils/metrics');
const {fetchSockets} = require("./wsServer");
const {IDENTITIES} = require("./assistHelper");
const {logger} = require('./logger');
const respond = function (req, res, data) {
logger.debug("responding with data: ", JSON.stringify(data))
let result = {data}
if (process.env.uws !== "true") {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(result));
} else {
res.cork(() => {
res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result));
});
}
const duration = performance.now() - req.startTs;
IncreaseTotalRequests();
RecordRequestDuration(req.method.toLowerCase(), res.handlerName, 200, duration/1000.0);
}
const getParticularSession = async function (roomId, filters) {
let connected_sockets = await fetchSockets(roomId);
if (connected_sockets.length === 0) {
return null;
}
let sessInfo;
for (let item of connected_sockets) {
if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo) {
sessInfo = item.handshake.query.sessionInfo;
break;
}
}
if (!sessInfo) {
return null;
}
if (!hasFilters(filters)) {
return sessInfo;
}
const result = isValidSession(sessInfo, filters.filter)
if (result.matched) {
return sessInfo;
}
return null;
}
const getAllSessions = async function (projectKey, filters, counters, onlineOnly= false) {
const sessions = [];
const connected_sockets = await fetchSockets();
if (connected_sockets.length === 0) {
return sessions;
}
const rooms = new Map();
for (let item of connected_sockets) {
// Prefilter checks
if (rooms.has(item.handshake.query.roomId)) {
continue;
}
if (item.handshake.query.projectKey !== projectKey || !item.handshake.query.sessionInfo) {
continue;
}
if (onlineOnly && item.handshake.query.identity !== IDENTITIES.session) {
continue;
}
// Mark this room as visited
rooms.set(item.handshake.query.roomId, true);
// Add session to the list without filtering
if (!hasFilters(filters)) {
sessions.push(item.handshake.query.sessionInfo);
continue;
}
// Add session to the list if it passes the filter
const result = isValidSession(item.handshake.query.sessionInfo, filters.filter)
if (result.matched) {
sessions.push(item.handshake.query.sessionInfo);
// Add filter name/value to counter
for (const [filterName, filterValue] of Object.entries(result.filters)) {
if (counters[filterName] === undefined) {
counters[filterName] = {};
}
if (counters[filterName][filterValue] === undefined) {
counters[filterName][filterValue] = 0;
}
counters[filterName][filterValue] += 1;
}
}
}
return sessions
}
// Sort by projectKey
const socketsListByProject = async function (req, res) {
logger.debug("[WS]looking for available sessions");
res.handlerName = 'socketsListByProject';
const _projectKey = extractProjectKeyFromRequest(req);
const _sessionId = extractSessionIdFromRequest(req);
const filters = await extractPayloadFromRequest(req, res);
// find a particular session
if (_sessionId) {
const sessInfo = await getParticularSession(`${_projectKey}-${_sessionId}`, filters);
return respond(req, res, sessInfo);
}
// find all sessions for a project
const counters = {};
const sessions = await getAllSessions(_projectKey, filters, counters);
// send response
respond(req, res, sortPaginate(sessions, filters, counters));
}
// Sort by projectKey
const socketsLiveByProject = async function (req, res) {
logger.debug("[WS]looking for available LIVE sessions");
res.handlerName = 'socketsLiveByProject';
const _projectKey = extractProjectKeyFromRequest(req);
const _sessionId = extractSessionIdFromRequest(req);
const filters = await extractPayloadFromRequest(req, res);
// find a particular session
if (_sessionId) {
let sessInfo = await getParticularSession(`${_projectKey}-${_sessionId}`, filters);
return respond(req, res, sessInfo);
}
// find all sessions for a project
const counters = {};
const sessions = await getAllSessions(_projectKey, filters, counters, true);
// send response
respond(req, res, sortPaginate(sessions, filters, counters));
}
// Sort by roomID (projectKey+sessionId)
const socketsLiveBySession = async function (req, res) {
logger.debug("[WS]looking for LIVE session");
res.handlerName = 'socketsLiveBySession';
const _projectKey = extractProjectKeyFromRequest(req);
const _sessionId = extractSessionIdFromRequest(req);
const filters = await extractPayloadFromRequest(req, res);
// find a particular session
if (_sessionId) {
let sessInfo = await getParticularSession(`${_projectKey}-${_sessionId}`, filters);
return respond(req, res, sessInfo);
}
return respond(req, res, null);
}
// Sort by projectKey
const autocomplete = async function (req, res) {
logger.debug("[WS]autocomplete");
res.handlerName = 'autocomplete';
const _projectKey = extractProjectKeyFromRequest(req);
const filters = await extractPayloadFromRequest(req);
let results = [];
if (!hasQuery(filters)) {
return respond(req, res, results);
}
let connected_sockets = await fetchSockets();
if (connected_sockets.length === 0) {
return results;
}
const rooms = new Map();
for (let item of connected_sockets) {
if (rooms.has(item.handshake.query.roomId)) {
continue;
}
if (item.handshake.query.sessionInfo) {
if ((item.handshake.query.projectKey !== _projectKey) || (item.handshake.query.identity !== IDENTITIES.session)) {
continue;
}
// Mark this room as visited
rooms.set(item.handshake.query.roomId, true);
results.push(...getValidAttributes(item.handshake.query.sessionInfo, filters.query))
}
}
respond(req, res, uniqueAutocomplete(results));
}
module.exports = {
respond,
socketsListByProject,
socketsLiveByProject,
socketsLiveBySession,
autocomplete
}