Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit d83199f

Browse files
authored
Merge pull request #9 from apilytics/query-params
Send query parameters in addition to path in middlewares
2 parents f790686 + 5322732 commit d83199f

8 files changed

Lines changed: 81 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Send query parameters in addition to the path.
13+
1014
## [1.0.2] - 2022-01-16
1115

1216
### Added

packages/core/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const myApilyticsMiddleware = async (req, handler) => {
4747
sendApilyticsMetrics({
4848
apiKey,
4949
path: req.path,
50+
query: req.queryString,
5051
method: req.method,
5152
statusCode: res.statusCode,
5253
timeMillis: timer(),

packages/core/__tests__/index.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,40 @@ describe('sendApilyticsMetrics()', () => {
108108
});
109109
});
110110

111+
it('should send query parameters', async () => {
112+
sendApilyticsMetrics({
113+
...params,
114+
query: 'key=val&other=123',
115+
});
116+
117+
expect(requestSpy).toHaveBeenCalledTimes(1);
118+
119+
const data = JSON.parse(clientRequestMock.write.mock.calls[0]);
120+
expect(data).toHaveProperty('query', 'key=val&other=123');
121+
});
122+
123+
it('should not send empty query parameters', async () => {
124+
sendApilyticsMetrics({
125+
...params,
126+
query: undefined,
127+
});
128+
129+
expect(requestSpy).toHaveBeenCalledTimes(1);
130+
131+
let data = JSON.parse(clientRequestMock.write.mock.calls[0]);
132+
expect(data).not.toHaveProperty('query');
133+
134+
sendApilyticsMetrics({
135+
...params,
136+
query: '',
137+
});
138+
139+
expect(requestSpy).toHaveBeenCalledTimes(2);
140+
141+
data = JSON.parse(clientRequestMock.write.mock.calls[0]);
142+
expect(data).not.toHaveProperty('query');
143+
});
144+
111145
it('should hide HTTP errors in production', async () => {
112146
// @ts-ignore: Assigning to a read-only property.
113147
process.env.NODE_ENV = 'production';

packages/core/src/index.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,28 @@ interface Params {
88
method: string;
99
statusCode: number | null;
1010
timeMillis: number;
11+
query?: string;
1112
apilyticsIntegration?: string;
1213
integratedLibrary?: string;
1314
}
1415

15-
export const sendApilyticsMetrics = (params: Params): void => {
16-
const { apiKey, apilyticsIntegration, integratedLibrary, ...metrics } =
17-
params;
18-
const data = JSON.stringify(metrics);
19-
16+
export const sendApilyticsMetrics = ({
17+
apiKey,
18+
path,
19+
query,
20+
method,
21+
statusCode,
22+
timeMillis,
23+
apilyticsIntegration,
24+
integratedLibrary,
25+
}: Params): void => {
26+
const data = JSON.stringify({
27+
path,
28+
query: query || undefined,
29+
method,
30+
statusCode,
31+
timeMillis,
32+
});
2033
let apilyticsVersion = `${
2134
apilyticsIntegration ?? 'apilytics-node-core'
2235
}/${APILYTICS_VERSION};node/${process.versions.node}`;

packages/express/__tests__/index.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe('apilyticsMiddleware()', () => {
9999
expect(data['timeMillis']).toEqual(Math.trunc(data['timeMillis']));
100100
});
101101

102-
it('should not send query parameters', async () => {
102+
it('should send query parameters', async () => {
103103
const agent = createAgent({ apiKey });
104104
const response = await agent.post('/dummy/123/path/?param=foo&param2=bar');
105105
expect(response.status).toEqual(201);
@@ -126,6 +126,7 @@ describe('apilyticsMiddleware()', () => {
126126
const data = JSON.parse(clientRequestMock.write.mock.calls[0]);
127127
expect(data).toStrictEqual({
128128
path: '/dummy/123/path/',
129+
query: '?param=foo&param2=bar',
129130
method: 'POST',
130131
statusCode: 201,
131132
timeMillis: expect.any(Number),

packages/express/src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { URL } from 'url';
2+
13
import { milliSecondTimer, sendApilyticsMetrics } from '@apilytics/core';
24
import type { NextFunction, Request, RequestHandler, Response } from 'express';
35

@@ -15,9 +17,14 @@ export const apilyticsMiddleware = (
1517
return (req: Request, res: Response, next: NextFunction): void => {
1618
const timer = milliSecondTimer();
1719
res.on('finish', () => {
20+
const { pathname: path, search: query } = new URL(
21+
req.originalUrl,
22+
'http://_', // Cannot parse a relative URL, so make it absolute.
23+
);
1824
sendApilyticsMetrics({
1925
apiKey,
20-
path: req.path,
26+
path,
27+
query,
2128
method: req.method,
2229
statusCode: res.statusCode,
2330
timeMillis: timer(),

packages/next/__tests__/index.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ describe('withApilytics()', () => {
119119
expect(data['timeMillis']).toEqual(Math.trunc(data['timeMillis']));
120120
});
121121

122-
it('should not send query parameters', async () => {
122+
it('should send query parameters', async () => {
123123
const agent = createAgent({ apiKey });
124124
const response = await agent.post('/dummy/123/path/?param=foo&param2=bar');
125125
expect(response.status).toEqual(201);
@@ -146,6 +146,7 @@ describe('withApilytics()', () => {
146146
const data = JSON.parse(clientRequestMock.write.mock.calls[0]);
147147
expect(data).toStrictEqual({
148148
path: '/dummy/123/path/',
149+
query: '?param=foo&param2=bar',
149150
method: 'POST',
150151
statusCode: 201,
151152
timeMillis: expect.any(Number),
@@ -178,7 +179,7 @@ describe('withApilytics()', () => {
178179
});
179180
});
180181

181-
it('should use empty strings as default values', async () => {
182+
it('should use correct default values', async () => {
182183
const agent = createAgent({ apiKey });
183184
const response = await agent.get('/empty');
184185
expect(response.status).toEqual(200);

packages/next/src/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { URL } from 'url';
2+
13
import { milliSecondTimer, sendApilyticsMetrics } from '@apilytics/core';
24
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';
35

@@ -24,9 +26,17 @@ export const withApilytics = <T>(
2426
// otherwise, we could end up sending NextApiResponse's default 200 status.
2527
statusCode = res.statusCode;
2628
} finally {
29+
let path, query;
30+
if (req.url) {
31+
({ pathname: path, search: query } = new URL(
32+
req.url,
33+
'http://_', // Cannot parse a relative URL, so make it absolute.
34+
));
35+
}
2736
sendApilyticsMetrics({
2837
apiKey,
29-
path: req.url?.split('?')[0] ?? '',
38+
path: path ?? '',
39+
query,
3040
method: req.method ?? '',
3141
statusCode,
3242
timeMillis: timer(),

0 commit comments

Comments
 (0)