-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathharFormatter.ts
More file actions
102 lines (90 loc) · 3.53 KB
/
harFormatter.ts
File metadata and controls
102 lines (90 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import type {
Request as HarRequest,
Response as HarResponse,
Header as HarHeader,
} from "har-format";
import { IncomingHttpHeaders, OutgoingHttpHeaders } from "http";
import { Request, Response } from "express";
import { RequestMethod } from "../../types";
export const getHarHeaders = (headers: IncomingHttpHeaders | OutgoingHttpHeaders): HarHeader[] => {
const harHeaders: HarHeader[] = [];
for (const headerName in headers) {
const headerValue = headers[headerName];
// Header values can be string | string[] according to Node.js typings,
// but HAR format requires a string, so we need to handle this.
if (headerValue) {
const value = Array.isArray(headerValue) ? headerValue.join('; ') : headerValue;
harHeaders.push({ name: headerName, value: value.toString() });
}
}
return harHeaders;
};
export const getPostData = (req: Request): HarRequest['postData'] => {
if ([RequestMethod.POST, RequestMethod.PUT, RequestMethod.PATCH].includes(req.method as RequestMethod)) {
const postData: any = {
mimeType: req.get('Content-Type') || 'application/json',
text: '',
params: [],
};
// When the body is URL-encoded, the body should be converted into params
if (postData.mimeType === 'application/x-www-form-urlencoded' && typeof req.body === 'object') {
postData.params = Object.keys(req.body).map(key => ({
name: key,
value: req.body[key],
}));
} else if (req.body) {
try {
postData.text = typeof req.body === 'string' ? req.body : JSON.stringify(req.body);
} catch (error) {
postData.text = "";
}
}
return postData;
}
return undefined;
}
export const getHarRequestQueryString = (req: Request): HarRequest['queryString'] => {
const queryObject: Request['query'] = req.query;
const queryString: HarRequest['queryString'] = [];
for (const [name, value] of Object.entries(queryObject)) {
if (Array.isArray(value)) {
value.forEach(val => queryString.push({ name, value: val as string }));
} else {
queryString.push({ name, value: value as string });
}
}
return queryString;
}
export const buildHarRequest = (req: Request): HarRequest => {
const requestData = getPostData(req)
return {
method: req.method,
url: req.url,
httpVersion: req.httpVersion,
cookies: [],
headers: getHarHeaders(req.headers),
queryString: getHarRequestQueryString(req),
postData: requestData,
headersSize: -1, // not calculating for now
bodySize: requestData ? Buffer.byteLength(requestData.text!) : -1,
}
};
export const buildHarResponse = (res: Response, metadata?: any): HarResponse => {
const { body } = metadata;
const bodySize = body ? Buffer.byteLength(JSON.stringify(body || {})) : -1;
return {
status: res.statusCode,
statusText: res.statusMessage,
httpVersion: res.req.httpVersion,
cookies: [],
headers: getHarHeaders(res.getHeaders()),
content: {
size: bodySize, // same as bodySize since serving uncompressed
mimeType: res.get('Content-Type') || 'application/json',
text: JSON.stringify(body),
},
redirectURL: '', // todo: implement when we integrate rules to mocks
headersSize: -1, // not calculating for now
bodySize,
}
};