15815213711
2024-08-26 67b8b6731811983447e053d4396b3708c14dfe3c
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
'use strict';
const deferToConnect = require('defer-to-connect');
 
module.exports = request => {
    const timings = {
        start: Date.now(),
        socket: null,
        lookup: null,
        connect: null,
        upload: null,
        response: null,
        end: null,
        error: null,
        phases: {
            wait: null,
            dns: null,
            tcp: null,
            request: null,
            firstByte: null,
            download: null,
            total: null
        }
    };
 
    const handleError = origin => {
        const emit = origin.emit.bind(origin);
        origin.emit = (event, ...args) => {
            // Catches the `error` event
            if (event === 'error') {
                timings.error = Date.now();
                timings.phases.total = timings.error - timings.start;
 
                origin.emit = emit;
            }
 
            // Saves the original behavior
            return emit(event, ...args);
        };
    };
 
    let uploadFinished = false;
    const onUpload = () => {
        timings.upload = Date.now();
        timings.phases.request = timings.upload - timings.connect;
    };
 
    handleError(request);
 
    request.once('socket', socket => {
        timings.socket = Date.now();
        timings.phases.wait = timings.socket - timings.start;
 
        const lookupListener = () => {
            timings.lookup = Date.now();
            timings.phases.dns = timings.lookup - timings.socket;
        };
 
        socket.once('lookup', lookupListener);
 
        deferToConnect(socket, () => {
            timings.connect = Date.now();
 
            if (timings.lookup === null) {
                socket.removeListener('lookup', lookupListener);
                timings.lookup = timings.connect;
                timings.phases.dns = timings.lookup - timings.socket;
            }
 
            timings.phases.tcp = timings.connect - timings.lookup;
 
            if (uploadFinished && !timings.upload) {
                onUpload();
            }
        });
    });
 
    request.once('finish', () => {
        uploadFinished = true;
 
        if (timings.connect) {
            onUpload();
        }
    });
 
    request.once('response', response => {
        timings.response = Date.now();
        timings.phases.firstByte = timings.response - timings.upload;
 
        handleError(response);
 
        response.once('end', () => {
            timings.end = Date.now();
            timings.phases.download = timings.end - timings.response;
            timings.phases.total = timings.end - timings.start;
        });
    });
 
    return timings;
};