@fluwa-tool/sdk 1.0.39 → 1.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -14,7 +14,7 @@ class XMLHttpRequestInterceptor {
|
|
|
14
14
|
this.sessionId = sessionId;
|
|
15
15
|
this.appName = appName;
|
|
16
16
|
this.isInstalled = false;
|
|
17
|
-
this.urlFilter = null;
|
|
17
|
+
this.urlFilter = null;
|
|
18
18
|
this.urlFilter = urlFilter || null;
|
|
19
19
|
}
|
|
20
20
|
install() {
|
|
@@ -22,18 +22,15 @@ class XMLHttpRequestInterceptor {
|
|
|
22
22
|
this.logger.warn('XMLHttpRequest interceptor já foi instalado');
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
// Verificar se XMLHttpRequest está disponível (apenas em navegadores)
|
|
26
25
|
if (typeof XMLHttpRequest === 'undefined') {
|
|
27
26
|
this.logger.debug('XMLHttpRequest não disponível nesse ambiente (requer navegador)');
|
|
28
27
|
return;
|
|
29
28
|
}
|
|
30
29
|
const self = this;
|
|
31
30
|
const originalXHR = XMLHttpRequest.prototype;
|
|
32
|
-
// Armazenar referência ao open original
|
|
33
31
|
this.originalOpen = originalXHR.open;
|
|
34
32
|
this.originalSend = originalXHR.send;
|
|
35
33
|
this.originalSetRequestHeader = originalXHR.setRequestHeader;
|
|
36
|
-
// Interceptar open()
|
|
37
34
|
originalXHR.open = function (method, url, ...args) {
|
|
38
35
|
const xhr = this;
|
|
39
36
|
xhr._fluwaMethod = method.toUpperCase();
|
|
@@ -43,7 +40,6 @@ class XMLHttpRequestInterceptor {
|
|
|
43
40
|
xhr._fluwaStartTime = Date.now();
|
|
44
41
|
return self.originalOpen.apply(this, [method, url, ...args]);
|
|
45
42
|
};
|
|
46
|
-
// Interceptar setRequestHeader()
|
|
47
43
|
originalXHR.setRequestHeader = function (header, value) {
|
|
48
44
|
const xhr = this;
|
|
49
45
|
if (!xhr._fluwaHeaders) {
|
|
@@ -52,7 +48,6 @@ class XMLHttpRequestInterceptor {
|
|
|
52
48
|
xhr._fluwaHeaders[header] = value;
|
|
53
49
|
return self.originalSetRequestHeader.apply(this, [header, value]);
|
|
54
50
|
};
|
|
55
|
-
// Interceptar send()
|
|
56
51
|
this.originalSend = originalXHR.send;
|
|
57
52
|
originalXHR.send = function (body) {
|
|
58
53
|
const xhr = this;
|
|
@@ -60,8 +55,6 @@ class XMLHttpRequestInterceptor {
|
|
|
60
55
|
const url = xhr._fluwaUrl;
|
|
61
56
|
const requestId = xhr._fluwaRequestId;
|
|
62
57
|
const headers = xhr._fluwaHeaders || {};
|
|
63
|
-
// ✅ Verificar URL Filter: ignorar requisições para servidor Fluwa ou URLs excluídas
|
|
64
|
-
// Isso previne loops infinitos onde o servidor Fluwa faz requisições que são interceptadas
|
|
65
58
|
if (self.urlFilter && !self.urlFilter.shouldIntercept(url)) {
|
|
66
59
|
self.logger.debug(`🔧 [XMLHttpRequestInterceptor] Ignorando URL excluída: ${url} (bypass filtering)`);
|
|
67
60
|
return self.originalSend.apply(this, [body]);
|
|
@@ -77,51 +70,92 @@ class XMLHttpRequestInterceptor {
|
|
|
77
70
|
appName: self.appName,
|
|
78
71
|
source: types_1.RequestSource.REAL,
|
|
79
72
|
};
|
|
80
|
-
// Logar início imediatamente
|
|
81
73
|
self.requestLogger.logStart(requestMetadata).catch(() => { });
|
|
82
|
-
// Interceptar mudanças de estado
|
|
83
74
|
const originalOnReadyStateChange = xhr.onreadystatechange;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
75
|
+
// Verificar mock com retry
|
|
76
|
+
const checkMockWithRetry = async () => {
|
|
77
|
+
let mockResponse = await self.mockResolver.resolve(method, url);
|
|
78
|
+
if (!mockResponse) {
|
|
79
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
80
|
+
mockResponse = await self.mockResolver.resolve(method, url);
|
|
81
|
+
}
|
|
82
|
+
return mockResponse;
|
|
83
|
+
};
|
|
84
|
+
checkMockWithRetry().then(mockResponse => {
|
|
85
|
+
if (mockResponse) {
|
|
86
|
+
// Mock encontrado - simular resposta
|
|
87
|
+
requestMetadata.source = types_1.RequestSource.MOCK;
|
|
88
|
+
requestMetadata.status = mockResponse.status || 200;
|
|
89
|
+
requestMetadata.response = mockResponse.response;
|
|
90
|
+
const delay = mockResponse.delay || 0;
|
|
91
|
+
setTimeout(() => {
|
|
92
|
+
const duration = Date.now() - (xhr._fluwaStartTime || 0);
|
|
93
|
+
requestMetadata.duration = duration;
|
|
94
|
+
self.requestLogger.logComplete(requestMetadata).catch(() => { });
|
|
95
|
+
// Simular readyState = 4 chamando onreadystatechange 3x
|
|
96
|
+
try {
|
|
97
|
+
// Chamar para cada readyState
|
|
98
|
+
for (let state = 1; state <= 4; state++) {
|
|
99
|
+
Object.defineProperty(xhr, 'readyState', { value: state, configurable: true, writable: true });
|
|
100
|
+
if (state === 4) {
|
|
101
|
+
Object.defineProperty(xhr, 'status', { value: mockResponse.status || 200, configurable: true, writable: true });
|
|
102
|
+
Object.defineProperty(xhr, 'statusText', { value: 'Mock', configurable: true, writable: true });
|
|
103
|
+
Object.defineProperty(xhr, 'responseText', { value: JSON.stringify(mockResponse.response), configurable: true, writable: true });
|
|
104
|
+
Object.defineProperty(xhr, 'response', { value: mockResponse.response, configurable: true, writable: true });
|
|
105
|
+
}
|
|
106
|
+
if (originalOnReadyStateChange) {
|
|
107
|
+
originalOnReadyStateChange.call(xhr);
|
|
108
|
+
}
|
|
93
109
|
}
|
|
94
110
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
requestMetadata.response = `[${xhr.responseType}]`;
|
|
101
|
-
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
self.logger.debug('Erro ao simular resposta mockada, fallback para servidor real:', error);
|
|
113
|
+
self.originalSend.apply(xhr, [body]);
|
|
102
114
|
}
|
|
103
|
-
}
|
|
104
|
-
|
|
115
|
+
}, delay);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Sem mock - fazer request real
|
|
119
|
+
xhr.onreadystatechange = function (event) {
|
|
120
|
+
if (xhr.readyState === 4) {
|
|
121
|
+
requestMetadata.status = xhr.status;
|
|
105
122
|
try {
|
|
106
|
-
if (xhr.
|
|
107
|
-
|
|
123
|
+
if (xhr.responseType === '' || xhr.responseType === 'text') {
|
|
124
|
+
if (xhr.responseText) {
|
|
125
|
+
requestMetadata.response = self.safeParseBody(xhr.responseText);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (xhr.response) {
|
|
129
|
+
if (typeof xhr.response === 'string') {
|
|
130
|
+
requestMetadata.response = self.safeParseBody(xhr.response);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
requestMetadata.response = `[${xhr.responseType}]`;
|
|
134
|
+
}
|
|
108
135
|
}
|
|
109
136
|
}
|
|
110
|
-
catch {
|
|
111
|
-
|
|
137
|
+
catch (e) {
|
|
138
|
+
try {
|
|
139
|
+
if (xhr.responseText) {
|
|
140
|
+
requestMetadata.response = xhr.responseText;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
requestMetadata.response = undefined;
|
|
145
|
+
}
|
|
112
146
|
}
|
|
147
|
+
const duration = Date.now() - (xhr._fluwaStartTime || 0);
|
|
148
|
+
requestMetadata.duration = duration;
|
|
149
|
+
self.requestLogger.logComplete(requestMetadata).catch(() => { });
|
|
113
150
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
// Chamar send original
|
|
124
|
-
return self.originalSend.apply(this, [body]);
|
|
151
|
+
if (originalOnReadyStateChange) {
|
|
152
|
+
originalOnReadyStateChange.call(this, event);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
self.originalSend.apply(xhr, [body]);
|
|
156
|
+
}).catch(() => {
|
|
157
|
+
self.originalSend.apply(xhr, [body]);
|
|
158
|
+
});
|
|
125
159
|
};
|
|
126
160
|
this.isInstalled = true;
|
|
127
161
|
this.logger.success('XMLHttpRequest interceptor instalado');
|