1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | class HARBase {
|
8 | readonly custom: Map<string, any>;
|
9 | constructor(data: any) {
|
10 | if (!data || typeof data !== 'object') {
|
11 | throw 'First parameter is expected to be an object';
|
12 | }
|
13 | this.custom = new Map();
|
14 | }
|
15 |
|
16 | static safeDate(data: any): Date {
|
17 | const date = new Date(data);
|
18 | if (!Number.isNaN(date.getTime())) {
|
19 | return date;
|
20 | }
|
21 | throw 'Invalid date format';
|
22 | }
|
23 |
|
24 | static safeNumber(data: any): number {
|
25 | const result = Number(data);
|
26 | if (!Number.isNaN(result)) {
|
27 | return result;
|
28 | }
|
29 | throw 'Casting to number results in NaN';
|
30 | }
|
31 |
|
32 | static optionalNumber(data: any): number|undefined {
|
33 | return data !== undefined ? HARBase.safeNumber(data) : undefined;
|
34 | }
|
35 |
|
36 | static optionalString(data: any): string|undefined {
|
37 | return data !== undefined ? String(data) : undefined;
|
38 | }
|
39 |
|
40 | customAsString(name: string): string|undefined {
|
41 | const value = this.custom.get(name);
|
42 | if (!value) {
|
43 | return undefined;
|
44 | }
|
45 | return String(value);
|
46 | }
|
47 |
|
48 | customAsNumber(name: string): number|undefined {
|
49 | const value = this.custom.get(name);
|
50 | if (!value) {
|
51 | return undefined;
|
52 | }
|
53 | const numberValue = Number(value);
|
54 | if (Number.isNaN(numberValue)) {
|
55 | return undefined;
|
56 | }
|
57 | return numberValue;
|
58 | }
|
59 |
|
60 | customAsArray(name: string): any[]|undefined {
|
61 | const value = this.custom.get(name);
|
62 | if (!value) {
|
63 | return undefined;
|
64 | }
|
65 | return Array.isArray(value) ? value : undefined;
|
66 | }
|
67 |
|
68 | customInitiator(): HARInitiator|undefined {
|
69 | return this.custom.get('initiator');
|
70 | }
|
71 | }
|
72 |
|
73 | export class HARRoot extends HARBase {
|
74 | log: HARLog;
|
75 | constructor(data: any) {
|
76 | super(data);
|
77 | this.log = new HARLog(data['log']);
|
78 | }
|
79 | }
|
80 |
|
81 | export class HARLog extends HARBase {
|
82 | version: string;
|
83 | creator: HARCreator;
|
84 | browser: HARCreator|undefined;
|
85 | pages: HARPage[];
|
86 | entries: HAREntry[];
|
87 | comment: string|undefined;
|
88 | constructor(data: any) {
|
89 | super(data);
|
90 | this.version = String(data['version']);
|
91 | this.creator = new HARCreator(data['creator']);
|
92 | this.browser = data['browser'] ? new HARCreator(data['browser']) : undefined;
|
93 | this.pages = Array.isArray(data['pages']) ? data['pages'].map(page => new HARPage(page)) : [];
|
94 | if (!Array.isArray(data['entries'])) {
|
95 | throw 'log.entries is expected to be an array';
|
96 | }
|
97 | this.entries = data['entries'].map(entry => new HAREntry(entry));
|
98 | this.comment = HARBase.optionalString(data['comment']);
|
99 | }
|
100 | }
|
101 |
|
102 | class HARCreator extends HARBase {
|
103 | name: string;
|
104 | version: string;
|
105 | comment: string|undefined;
|
106 | constructor(data: any) {
|
107 | super(data);
|
108 | this.name = String(data['name']);
|
109 | this.version = String(data['version']);
|
110 | this.comment = HARBase.optionalString(data['comment']);
|
111 | }
|
112 | }
|
113 |
|
114 | export class HARPage extends HARBase {
|
115 | startedDateTime: Date;
|
116 | id: string;
|
117 | title: string;
|
118 | pageTimings: HARPageTimings;
|
119 | comment: string|undefined;
|
120 | constructor(data: any) {
|
121 | super(data);
|
122 | this.startedDateTime = HARBase.safeDate(data['startedDateTime']);
|
123 | this.id = String(data['id']);
|
124 | this.title = String(data['title']);
|
125 | this.pageTimings = new HARPageTimings(data['pageTimings']);
|
126 | this.comment = HARBase.optionalString(data['comment']);
|
127 | }
|
128 | }
|
129 |
|
130 | class HARPageTimings extends HARBase {
|
131 | onContentLoad: number|undefined;
|
132 | onLoad: number|undefined;
|
133 | comment: string|undefined;
|
134 | constructor(data: any) {
|
135 | super(data);
|
136 | this.onContentLoad = HARBase.optionalNumber(data['onContentLoad']);
|
137 | this.onLoad = HARBase.optionalNumber(data['onLoad']);
|
138 | this.comment = HARBase.optionalString(data['comment']);
|
139 | }
|
140 | }
|
141 |
|
142 | export class HAREntry extends HARBase {
|
143 | pageref: string|undefined;
|
144 | startedDateTime: Date;
|
145 | time: number;
|
146 | request: HARRequest;
|
147 | response: HARResponse;
|
148 | cache: {};
|
149 | timings: HARTimings;
|
150 | serverIPAddress: string|undefined;
|
151 | connection: string|undefined;
|
152 | comment: string|undefined;
|
153 | constructor(data: any) {
|
154 | super(data);
|
155 | this.pageref = HARBase.optionalString(data['pageref']);
|
156 | this.startedDateTime = HARBase.safeDate(data['startedDateTime']);
|
157 | this.time = HARBase.safeNumber(data['time']);
|
158 | this.request = new HARRequest(data['request']);
|
159 | this.response = new HARResponse(data['response']);
|
160 | this.cache = {};
|
161 | this.timings = new HARTimings(data['timings']);
|
162 | this.serverIPAddress = HARBase.optionalString(data['serverIPAddress']);
|
163 | this.connection = HARBase.optionalString(data['connection']);
|
164 | this.comment = HARBase.optionalString(data['comment']);
|
165 |
|
166 |
|
167 | this.custom.set('fromCache', HARBase.optionalString(data['_fromCache']));
|
168 | this.custom.set('initiator', this.importInitiator(data['_initiator']));
|
169 | this.custom.set('priority', HARBase.optionalString(data['_priority']));
|
170 | this.custom.set('resourceType', HARBase.optionalString(data['_resourceType']));
|
171 | this.custom.set('webSocketMessages', this.importWebSocketMessages(data['_webSocketMessages']));
|
172 | }
|
173 |
|
174 | private importInitiator(initiator: any): HARInitiator|undefined {
|
175 | if (typeof initiator !== 'object') {
|
176 | return;
|
177 | }
|
178 |
|
179 | return new HARInitiator(initiator);
|
180 | }
|
181 |
|
182 | private importWebSocketMessages(inputMessages: any): HARWebSocketMessage[]|undefined {
|
183 | if (!Array.isArray(inputMessages)) {
|
184 | return;
|
185 | }
|
186 |
|
187 | const outputMessages = [];
|
188 | for (const message of inputMessages) {
|
189 | if (typeof message !== 'object') {
|
190 | return;
|
191 | }
|
192 | outputMessages.push(new HARWebSocketMessage(message));
|
193 | }
|
194 | return outputMessages;
|
195 | }
|
196 | }
|
197 |
|
198 | class HARRequest extends HARBase {
|
199 | method: string;
|
200 | url: string;
|
201 | httpVersion: string;
|
202 | cookies: HARCookie[];
|
203 | headers: HARHeader[];
|
204 | queryString: HARQueryString[];
|
205 | postData: HARPostData|undefined;
|
206 | headersSize: number;
|
207 | bodySize: number;
|
208 | comment: string|undefined;
|
209 | constructor(data: any) {
|
210 | super(data);
|
211 | this.method = String(data['method']);
|
212 | this.url = String(data['url']);
|
213 | this.httpVersion = String(data['httpVersion']);
|
214 | this.cookies = Array.isArray(data['cookies']) ? data['cookies'].map(cookie => new HARCookie(cookie)) : [];
|
215 | this.headers = Array.isArray(data['headers']) ? data['headers'].map(header => new HARHeader(header)) : [];
|
216 | this.queryString = Array.isArray(data['queryString']) ? data['queryString'].map(qs => new HARQueryString(qs)) : [];
|
217 | this.postData = data['postData'] ? new HARPostData(data['postData']) : undefined;
|
218 | this.headersSize = HARBase.safeNumber(data['headersSize']);
|
219 | this.bodySize = HARBase.safeNumber(data['bodySize']);
|
220 | this.comment = HARBase.optionalString(data['comment']);
|
221 | }
|
222 | }
|
223 |
|
224 | class HARResponse extends HARBase {
|
225 | status: number;
|
226 | statusText: string;
|
227 | httpVersion: string;
|
228 | cookies: HARCookie[];
|
229 | headers: HARHeader[];
|
230 | content: HARContent;
|
231 | redirectURL: string;
|
232 | headersSize: number;
|
233 | bodySize: number;
|
234 | comment: string|undefined;
|
235 | constructor(data: any) {
|
236 | super(data);
|
237 | this.status = HARBase.safeNumber(data['status']);
|
238 | this.statusText = String(data['statusText']);
|
239 | this.httpVersion = String(data['httpVersion']);
|
240 | this.cookies = Array.isArray(data['cookies']) ? data['cookies'].map(cookie => new HARCookie(cookie)) : [];
|
241 | this.headers = Array.isArray(data['headers']) ? data['headers'].map(header => new HARHeader(header)) : [];
|
242 | this.content = new HARContent(data['content']);
|
243 | this.redirectURL = String(data['redirectURL']);
|
244 | this.headersSize = HARBase.safeNumber(data['headersSize']);
|
245 | this.bodySize = HARBase.safeNumber(data['bodySize']);
|
246 | this.comment = HARBase.optionalString(data['comment']);
|
247 |
|
248 |
|
249 | this.custom.set('transferSize', HARBase.optionalNumber(data['_transferSize']));
|
250 | this.custom.set('error', HARBase.optionalString(data['_error']));
|
251 | }
|
252 | }
|
253 |
|
254 | class HARCookie extends HARBase {
|
255 | name: string;
|
256 | value: string;
|
257 | path: string|undefined;
|
258 | domain: string|undefined;
|
259 | expires: Date|undefined;
|
260 | httpOnly: boolean|undefined;
|
261 | secure: boolean|undefined;
|
262 | comment: string|undefined;
|
263 | constructor(data: any) {
|
264 | super(data);
|
265 | this.name = String(data['name']);
|
266 | this.value = String(data['value']);
|
267 | this.path = HARBase.optionalString(data['path']);
|
268 | this.domain = HARBase.optionalString(data['domain']);
|
269 | this.expires = data['expires'] ? HARBase.safeDate(data['expires']) : undefined;
|
270 | this.httpOnly = data['httpOnly'] !== undefined ? Boolean(data['httpOnly']) : undefined;
|
271 | this.secure = data['secure'] !== undefined ? Boolean(data['secure']) : undefined;
|
272 | this.comment = HARBase.optionalString(data['comment']);
|
273 | }
|
274 | }
|
275 |
|
276 | class HARHeader extends HARBase {
|
277 | name: string;
|
278 | value: string;
|
279 | comment: string|undefined;
|
280 | constructor(data: any) {
|
281 | super(data);
|
282 | this.name = String(data['name']);
|
283 | this.value = String(data['value']);
|
284 | this.comment = HARBase.optionalString(data['comment']);
|
285 | }
|
286 | }
|
287 |
|
288 | class HARQueryString extends HARBase {
|
289 | name: string;
|
290 | value: string;
|
291 | comment: string|undefined;
|
292 | constructor(data: any) {
|
293 | super(data);
|
294 | this.name = String(data['name']);
|
295 | this.value = String(data['value']);
|
296 | this.comment = HARBase.optionalString(data['comment']);
|
297 | }
|
298 | }
|
299 |
|
300 | class HARPostData extends HARBase {
|
301 | mimeType: string;
|
302 | params: HARParam[];
|
303 | text: string;
|
304 | comment: string|undefined;
|
305 | constructor(data: any) {
|
306 | super(data);
|
307 | this.mimeType = String(data['mimeType']);
|
308 | this.params = Array.isArray(data['params']) ? data['params'].map(param => new HARParam(param)) : [];
|
309 | this.text = String(data['text']);
|
310 | this.comment = HARBase.optionalString(data['comment']);
|
311 | }
|
312 | }
|
313 |
|
314 | export class HARParam extends HARBase {
|
315 | name: string;
|
316 | value: string|undefined;
|
317 | fileName: string|undefined;
|
318 | contentType: string|undefined;
|
319 | comment: string|undefined;
|
320 | constructor(data: any) {
|
321 | super(data);
|
322 | this.name = String(data['name']);
|
323 | this.value = HARBase.optionalString(data['value']);
|
324 | this.fileName = HARBase.optionalString(data['fileName']);
|
325 | this.contentType = HARBase.optionalString(data['contentType']);
|
326 | this.comment = HARBase.optionalString(data['comment']);
|
327 | }
|
328 | }
|
329 |
|
330 | class HARContent extends HARBase {
|
331 | size: number;
|
332 | compression: number|undefined;
|
333 | mimeType: string;
|
334 | text: string|undefined;
|
335 | encoding: string|undefined;
|
336 | comment: string|undefined;
|
337 | constructor(data: any) {
|
338 | super(data);
|
339 | this.size = HARBase.safeNumber(data['size']);
|
340 | this.compression = HARBase.optionalNumber(data['compression']);
|
341 | this.mimeType = String(data['mimeType']);
|
342 | this.text = HARBase.optionalString(data['text']);
|
343 | this.encoding = HARBase.optionalString(data['encoding']);
|
344 | this.comment = HARBase.optionalString(data['comment']);
|
345 | }
|
346 | }
|
347 |
|
348 | export class HARTimings extends HARBase {
|
349 | blocked: number|undefined;
|
350 | dns: number|undefined;
|
351 | connect: number|undefined;
|
352 | send: number;
|
353 | wait: number;
|
354 | receive: number;
|
355 | ssl: number|undefined;
|
356 | comment: string|undefined;
|
357 | constructor(data: any) {
|
358 | super(data);
|
359 | this.blocked = HARBase.optionalNumber(data['blocked']);
|
360 | this.dns = HARBase.optionalNumber(data['dns']);
|
361 | this.connect = HARBase.optionalNumber(data['connect']);
|
362 | this.send = HARBase.safeNumber(data['send']);
|
363 | this.wait = HARBase.safeNumber(data['wait']);
|
364 | this.receive = HARBase.safeNumber(data['receive']);
|
365 | this.ssl = HARBase.optionalNumber(data['ssl']);
|
366 | this.comment = HARBase.optionalString(data['comment']);
|
367 |
|
368 |
|
369 | this.custom.set('blocked_queueing', HARBase.optionalNumber(data['_blocked_queueing']));
|
370 | this.custom.set('blocked_proxy', HARBase.optionalNumber(data['_blocked_proxy']));
|
371 | }
|
372 | }
|
373 |
|
374 | export class HARInitiator extends HARBase {
|
375 | type: string|undefined;
|
376 | url: string|undefined;
|
377 | lineNumber: number|undefined;
|
378 | |
379 |
|
380 |
|
381 | constructor(data: any) {
|
382 | super(data);
|
383 | this.type = HARBase.optionalString(data['type']);
|
384 | this.url = HARBase.optionalString(data['url']);
|
385 | this.lineNumber = HARBase.optionalNumber(data['lineNumber']);
|
386 | }
|
387 | }
|
388 |
|
389 | class HARWebSocketMessage extends HARBase {
|
390 | time: number|undefined;
|
391 | opcode: number|undefined;
|
392 | data: string|undefined;
|
393 | type: string|undefined;
|
394 | constructor(data: any) {
|
395 | super(data);
|
396 | this.time = HARBase.optionalNumber(data['time']);
|
397 | this.opcode = HARBase.optionalNumber(data['opcode']);
|
398 | this.data = HARBase.optionalString(data['data']);
|
399 | this.type = HARBase.optionalString(data['type']);
|
400 | }
|
401 | }
|