Skip to content

Commit 92a4800

Browse files
authored
feat: move rrweb event stream to client and query through /api/clickhouse-proxy (#755)
1 parent b4b5f6b commit 92a4800

File tree

9 files changed

+225
-269
lines changed

9 files changed

+225
-269
lines changed

.changeset/neat-badgers-matter.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@hyperdx/common-utils": patch
3+
"@hyperdx/api": patch
4+
"@hyperdx/app": patch
5+
---
6+
7+
feat: move rrweb event fetching to the client instead of an api route

packages/api/src/api-app.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ app.use('/', routers.rootRouter);
8989
app.use('/alerts', isUserAuthenticated, routers.alertsRouter);
9090
app.use('/dashboards', isUserAuthenticated, routers.dashboardRouter);
9191
app.use('/me', isUserAuthenticated, routers.meRouter);
92-
app.use('/sessions', isUserAuthenticated, routers.sessionsRouter);
9392
app.use('/team', isUserAuthenticated, routers.teamRouter);
9493
app.use('/webhooks', isUserAuthenticated, routers.webhooksRouter);
9594
app.use('/datasources', isUserAuthenticated, routers.datasourceRouter);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import express from 'express';
2+
import { z } from 'zod';
3+
4+
export function validateRequestHeaders<T extends z.Schema>(schema: T) {
5+
return function (
6+
req: express.Request,
7+
res: express.Response,
8+
next: express.NextFunction,
9+
) {
10+
const parsed = schema.safeParse(req.headers);
11+
if (!parsed.success) {
12+
return res.status(400).json({ type: 'Headers', errors: parsed.error });
13+
}
14+
15+
return next();
16+
};
17+
}

packages/api/src/routers/api/clickhouseProxy.ts

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import express, { Request, Response } from 'express';
1+
import express, { RequestHandler, Response } from 'express';
22
import { createProxyMiddleware } from 'http-proxy-middleware';
33
import { z } from 'zod';
44
import { validateRequest } from 'zod-express-middleware';
55

66
import { getConnectionById } from '@/controllers/connection';
77
import { getNonNullUserWithTeam } from '@/middleware/auth';
8+
import { validateRequestHeaders } from '@/middleware/validation';
89
import { objectIdSchema } from '@/utils/zod';
910

1011
const router = express.Router();
@@ -58,17 +59,22 @@ router.post(
5859
},
5960
);
6061

61-
router.get(
62-
'/*',
63-
validateRequest({
64-
query: z.object({
65-
hyperdx_connection_id: objectIdSchema,
66-
}),
62+
const hasConnectionId = validateRequestHeaders(
63+
z.object({
64+
'x-hyperdx-connection-id': objectIdSchema,
6765
}),
66+
);
67+
68+
const getConnection: RequestHandler =
69+
// prettier-ignore-next-line
6870
async (req, res, next) => {
6971
try {
7072
const { teamId } = getNonNullUserWithTeam(req);
71-
const { hyperdx_connection_id } = req.query;
73+
const connection_id = req.headers['x-hyperdx-connection-id']!; // ! because zod already validated
74+
delete req.headers['x-hyperdx-connection-id'];
75+
const hyperdx_connection_id = Array.isArray(connection_id)
76+
? connection_id.join('')
77+
: connection_id;
7278

7379
const connection = await getConnectionById(
7480
teamId.toString(),
@@ -93,13 +99,15 @@ router.get(
9399
console.error('Error fetching connection info:', e);
94100
next(e);
95101
}
96-
},
102+
};
103+
104+
const proxyMiddleware: RequestHandler =
105+
// prettier-ignore-next-line
97106
createProxyMiddleware({
98107
target: '', // doesn't matter. it should be overridden by the router
99108
changeOrigin: true,
100109
pathFilter: (path, _req) => {
101-
// TODO: allow other methods
102-
return _req.method === 'GET';
110+
return _req.method === 'GET' || _req.method === 'POST';
103111
},
104112
pathRewrite: {
105113
'^/clickhouse-proxy': '',
@@ -113,16 +121,20 @@ router.get(
113121
on: {
114122
proxyReq: (proxyReq, _req) => {
115123
const newPath = _req.params[0];
124+
// @ts-expect-error _req.query is type ParamQs, which doesn't play nicely with URLSearchParams. TODO: Replace with getting query params from _req.url eventually
116125
const qparams = new URLSearchParams(_req.query);
117-
qparams.delete('hyperdx_connection_id');
118126
if (_req._hdx_connection?.username && _req._hdx_connection?.password) {
119127
proxyReq.setHeader(
120128
'X-ClickHouse-User',
121129
_req._hdx_connection.username,
122130
);
123131
proxyReq.setHeader('X-ClickHouse-Key', _req._hdx_connection.password);
124132
}
125-
proxyReq.path = `/${newPath}?${qparams.toString()}`;
133+
if (_req.method === 'POST') {
134+
// TODO: Use fixRequestBody after this issue is resolved: https://github.com/chimurai/http-proxy-middleware/issues/1102
135+
proxyReq.write(_req.body);
136+
}
137+
proxyReq.path = `/${newPath}?${qparams}`;
126138
},
127139
proxyRes: (proxyRes, _req, res) => {
128140
// since clickhouse v24, the cors headers * will be attached to the response by default
@@ -158,7 +170,9 @@ router.get(
158170
// ...(config.IS_DEV && {
159171
// logger: console,
160172
// }),
161-
}),
162-
);
173+
});
174+
175+
router.get('/*', hasConnectionId, getConnection, proxyMiddleware);
176+
router.post('/*', hasConnectionId, getConnection, proxyMiddleware);
163177

164178
export default router;

packages/api/src/routers/api/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import dashboardRouter from './dashboards';
33
import datasourceRouter from './datasources';
44
import meRouter from './me';
55
import rootRouter from './root';
6-
import sessionsRouter from './sessions';
76
import teamRouter from './team';
87
import webhooksRouter from './webhooks';
98

@@ -13,7 +12,6 @@ export default {
1312
dashboardRouter,
1413
meRouter,
1514
rootRouter,
16-
sessionsRouter,
1715
teamRouter,
1816
webhooksRouter,
1917
};

packages/api/src/routers/api/sessions.ts

Lines changed: 0 additions & 152 deletions
This file was deleted.

packages/app/pages/api/[...all].ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const DEFAULT_SERVER_URL = `http://127.0.0.1:${process.env.HYPERDX_API_PORT}`;
66
export const config = {
77
api: {
88
externalResolver: true,
9-
bodyParser: true,
9+
bodyParser: false,
1010
},
1111
};
1212

@@ -17,12 +17,6 @@ export default (req: NextApiRequest, res: NextApiResponse) => {
1717
pathRewrite: { '^/api': '' },
1818
target: process.env.NEXT_PUBLIC_SERVER_URL || DEFAULT_SERVER_URL,
1919
autoRewrite: true,
20-
/**
21-
* Fix bodyParser
22-
**/
23-
on: {
24-
proxyReq: fixRequestBody,
25-
},
2620
// ...(IS_DEV && {
2721
// logger: console,
2822
// }),

0 commit comments

Comments
 (0)