@ngn-net/nestjs-telescope 0.2.4 → 0.2.6
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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/telescope.module.js +4 -0
- package/dist/ui/manifest.json +2 -2
- package/dist/watchers/http-client.watcher.js +161 -107
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -30,3 +30,4 @@ __exportStar(require("./watchers/command.watcher"), exports);
|
|
|
30
30
|
__exportStar(require("./watchers/model.watcher"), exports);
|
|
31
31
|
__exportStar(require("./watchers/notification.watcher"), exports);
|
|
32
32
|
__exportStar(require("./watchers/gate.watcher"), exports);
|
|
33
|
+
__exportStar(require("./watchers/http-client.watcher"), exports);
|
package/dist/telescope.module.js
CHANGED
|
@@ -25,6 +25,7 @@ const telescope_controller_1 = require("./controllers/telescope.controller");
|
|
|
25
25
|
const telescope_repository_service_1 = require("./storage/telescope-repository.service");
|
|
26
26
|
const telescope_entry_entity_1 = require("./storage/entities/telescope-entry.entity");
|
|
27
27
|
const http_request_watcher_1 = require("./watchers/http-request.watcher");
|
|
28
|
+
const http_client_watcher_1 = require("./watchers/http-client.watcher");
|
|
28
29
|
const query_watcher_1 = require("./watchers/query.watcher");
|
|
29
30
|
const cache_watcher_1 = require("./watchers/cache.watcher");
|
|
30
31
|
const queue_watcher_1 = require("./watchers/queue.watcher");
|
|
@@ -238,6 +239,7 @@ let TelescopeModule = TelescopeModule_1 = class TelescopeModule {
|
|
|
238
239
|
// Additional optional watchers (non-interceptors)
|
|
239
240
|
if (!options.enabledEntryTypes || options.enabledEntryTypes.includes(entry_type_enum_1.EntryType.HTTP_CLIENT)) {
|
|
240
241
|
providers.push(http_service_watcher_1.HttpServiceWatcher);
|
|
242
|
+
providers.push(http_client_watcher_1.HttpClientWatcher);
|
|
241
243
|
}
|
|
242
244
|
if (!options.enabledEntryTypes || options.enabledEntryTypes.includes(entry_type_enum_1.EntryType.COMMAND)) {
|
|
243
245
|
providers.push(command_watcher_1.CommandWatcher);
|
|
@@ -310,6 +312,8 @@ let TelescopeModule = TelescopeModule_1 = class TelescopeModule {
|
|
|
310
312
|
providers.push(query_watcher_1.QueryWatcher);
|
|
311
313
|
providers.push(log_watcher_1.LogWatcher);
|
|
312
314
|
providers.push(redis_watcher_1.RedisWatcher);
|
|
315
|
+
providers.push(http_client_watcher_1.HttpClientWatcher);
|
|
316
|
+
providers.push(http_service_watcher_1.HttpServiceWatcher);
|
|
313
317
|
// Optional modules/watchers if packages are present
|
|
314
318
|
try {
|
|
315
319
|
require('@nestjs/cache-manager');
|
package/dist/ui/manifest.json
CHANGED
|
@@ -67,128 +67,182 @@ let HttpClientWatcher = class HttpClientWatcher {
|
|
|
67
67
|
this.patched = true;
|
|
68
68
|
this.patch(http);
|
|
69
69
|
this.patch(https);
|
|
70
|
+
// Also patch follow-redirects if used by HTTP clients like Axios
|
|
71
|
+
try {
|
|
72
|
+
const followRedirects = require('follow-redirects');
|
|
73
|
+
if (followRedirects) {
|
|
74
|
+
if (followRedirects.http)
|
|
75
|
+
this.patch(followRedirects.http);
|
|
76
|
+
if (followRedirects.https)
|
|
77
|
+
this.patch(followRedirects.https);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
// follow-redirects not available, skip
|
|
82
|
+
}
|
|
70
83
|
}
|
|
71
84
|
patch(module) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
try {
|
|
86
|
+
const originalRequest = module.request;
|
|
87
|
+
if (typeof originalRequest !== 'function')
|
|
88
|
+
return;
|
|
89
|
+
const originalRequestBound = originalRequest.bind(module);
|
|
90
|
+
const self = this;
|
|
91
|
+
const customRequest = function (...args) {
|
|
92
|
+
const req = originalRequestBound(...args);
|
|
93
|
+
const startTime = Date.now();
|
|
94
|
+
// Resolve URL and method
|
|
95
|
+
let urlStr = '';
|
|
96
|
+
let method = 'GET';
|
|
97
|
+
try {
|
|
98
|
+
const firstArg = args[0];
|
|
99
|
+
if (typeof firstArg === 'string') {
|
|
100
|
+
urlStr = firstArg;
|
|
101
|
+
}
|
|
102
|
+
else if (firstArg instanceof URL) {
|
|
103
|
+
urlStr = firstArg.toString();
|
|
104
|
+
}
|
|
105
|
+
else if (typeof firstArg === 'object' && firstArg !== null) {
|
|
106
|
+
const { protocol, hostname, host, port, path: urlPath } = firstArg;
|
|
107
|
+
const proto = protocol || 'http:';
|
|
108
|
+
const h = hostname || host || 'localhost';
|
|
109
|
+
const p = port ? `:${port}` : '';
|
|
110
|
+
urlStr = `${proto}//${h}${p}${urlPath || '/'}`;
|
|
111
|
+
method = (firstArg.method || 'GET').toUpperCase();
|
|
112
|
+
}
|
|
85
113
|
}
|
|
86
|
-
|
|
87
|
-
urlStr =
|
|
114
|
+
catch {
|
|
115
|
+
urlStr = '';
|
|
88
116
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const h = hostname || host || 'localhost';
|
|
93
|
-
const p = port ? `:${port}` : '';
|
|
94
|
-
urlStr = `${proto}//${h}${p}${urlPath || '/'}`;
|
|
95
|
-
method = (firstArg.method || 'GET').toUpperCase();
|
|
117
|
+
// Ignore telescope's own internal paths and configured ignore list
|
|
118
|
+
if (self.telescope.shouldIgnorePath(urlStr)) {
|
|
119
|
+
return req;
|
|
96
120
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
// Skip if this type is disabled
|
|
122
|
+
if (!self.telescope.isEnabled(entry_type_enum_1.EntryType.HTTP_CLIENT)) {
|
|
123
|
+
return req;
|
|
124
|
+
}
|
|
125
|
+
// Capture request body chunks written
|
|
126
|
+
const reqChunks = [];
|
|
127
|
+
const originalWrite = req.write.bind(req);
|
|
128
|
+
const originalEnd = req.end.bind(req);
|
|
129
|
+
req.write = function (chunk, ...rest) {
|
|
130
|
+
if (chunk)
|
|
131
|
+
reqChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
132
|
+
return originalWrite(chunk, ...rest);
|
|
133
|
+
};
|
|
134
|
+
req.end = function (chunk, ...rest) {
|
|
135
|
+
if (chunk)
|
|
136
|
+
reqChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
137
|
+
return originalEnd(chunk, ...rest);
|
|
138
|
+
};
|
|
139
|
+
req.on('response', (res) => {
|
|
140
|
+
const resChunks = [];
|
|
141
|
+
res.on('data', (chunk) => {
|
|
142
|
+
resChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
143
|
+
});
|
|
144
|
+
res.on('end', () => {
|
|
145
|
+
const duration = Date.now() - startTime;
|
|
146
|
+
const requestBodyRaw = Buffer.concat(reqChunks).toString('utf8');
|
|
147
|
+
const responseBodyRaw = Buffer.concat(resChunks).toString('utf8');
|
|
148
|
+
let requestBody = requestBodyRaw;
|
|
149
|
+
let responseBody = responseBodyRaw;
|
|
150
|
+
try {
|
|
151
|
+
requestBody = JSON.parse(requestBodyRaw);
|
|
152
|
+
}
|
|
153
|
+
catch { /* keep raw */ }
|
|
154
|
+
try {
|
|
155
|
+
responseBody = JSON.parse(responseBodyRaw);
|
|
156
|
+
}
|
|
157
|
+
catch { /* keep raw */ }
|
|
158
|
+
// Sanitize headers — remove Authorization tokens from logs
|
|
159
|
+
const reqHeaders = { ...req.getHeaders?.() };
|
|
160
|
+
if (reqHeaders['authorization']) {
|
|
161
|
+
reqHeaders['authorization'] = '[REDACTED]';
|
|
162
|
+
}
|
|
163
|
+
self.telescope.record({
|
|
164
|
+
type: entry_type_enum_1.EntryType.HTTP_CLIENT,
|
|
165
|
+
content: {
|
|
166
|
+
method: method || (req.method || 'GET').toUpperCase(),
|
|
167
|
+
url: urlStr,
|
|
168
|
+
requestHeaders: reqHeaders,
|
|
169
|
+
requestBody,
|
|
170
|
+
responseStatus: res.statusCode,
|
|
171
|
+
responseHeaders: res.headers,
|
|
172
|
+
responseBody,
|
|
173
|
+
duration,
|
|
174
|
+
},
|
|
175
|
+
}).catch(() => { });
|
|
176
|
+
});
|
|
177
|
+
res.on('error', () => { });
|
|
131
178
|
});
|
|
132
|
-
|
|
179
|
+
req.on('error', (err) => {
|
|
133
180
|
const duration = Date.now() - startTime;
|
|
134
|
-
const requestBodyRaw = Buffer.concat(reqChunks).toString('utf8');
|
|
135
|
-
const responseBodyRaw = Buffer.concat(resChunks).toString('utf8');
|
|
136
|
-
let requestBody = requestBodyRaw;
|
|
137
|
-
let responseBody = responseBodyRaw;
|
|
138
|
-
try {
|
|
139
|
-
requestBody = JSON.parse(requestBodyRaw);
|
|
140
|
-
}
|
|
141
|
-
catch { /* keep raw */ }
|
|
142
|
-
try {
|
|
143
|
-
responseBody = JSON.parse(responseBodyRaw);
|
|
144
|
-
}
|
|
145
|
-
catch { /* keep raw */ }
|
|
146
|
-
// Sanitize headers — remove Authorization tokens from logs
|
|
147
|
-
const reqHeaders = { ...req.getHeaders?.() };
|
|
148
|
-
if (reqHeaders['authorization']) {
|
|
149
|
-
reqHeaders['authorization'] = '[REDACTED]';
|
|
150
|
-
}
|
|
151
181
|
self.telescope.record({
|
|
152
182
|
type: entry_type_enum_1.EntryType.HTTP_CLIENT,
|
|
153
183
|
content: {
|
|
154
|
-
method
|
|
184
|
+
method,
|
|
155
185
|
url: urlStr,
|
|
156
|
-
requestHeaders:
|
|
157
|
-
requestBody,
|
|
158
|
-
responseStatus:
|
|
159
|
-
|
|
160
|
-
|
|
186
|
+
requestHeaders: {},
|
|
187
|
+
requestBody: null,
|
|
188
|
+
responseStatus: 0,
|
|
189
|
+
responseBody: null,
|
|
190
|
+
error: err.message,
|
|
161
191
|
duration,
|
|
162
192
|
},
|
|
163
193
|
}).catch(() => { });
|
|
164
194
|
});
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
195
|
+
return req;
|
|
196
|
+
};
|
|
197
|
+
try {
|
|
198
|
+
const desc = Object.getOwnPropertyDescriptor(module, 'request');
|
|
199
|
+
if (desc && desc.configurable === false) {
|
|
200
|
+
// Can't redefine using defineProperty, try simple assignment
|
|
201
|
+
module.request = customRequest;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
Object.defineProperty(module, 'request', {
|
|
205
|
+
value: customRequest,
|
|
206
|
+
configurable: true,
|
|
207
|
+
writable: true,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
try {
|
|
213
|
+
module.request = customRequest;
|
|
214
|
+
}
|
|
215
|
+
catch { }
|
|
216
|
+
}
|
|
217
|
+
const customGet = function (...args) {
|
|
218
|
+
const req = module.request(...args);
|
|
219
|
+
req.end();
|
|
220
|
+
return req;
|
|
221
|
+
};
|
|
222
|
+
try {
|
|
223
|
+
const desc = Object.getOwnPropertyDescriptor(module, 'get');
|
|
224
|
+
if (desc && desc.configurable === false) {
|
|
225
|
+
// Can't redefine using defineProperty, try simple assignment
|
|
226
|
+
module.get = customGet;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
Object.defineProperty(module, 'get', {
|
|
230
|
+
value: customGet,
|
|
231
|
+
configurable: true,
|
|
232
|
+
writable: true,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
try {
|
|
238
|
+
module.get = customGet;
|
|
239
|
+
}
|
|
240
|
+
catch { }
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
// Prevent any crash
|
|
245
|
+
}
|
|
192
246
|
}
|
|
193
247
|
};
|
|
194
248
|
exports.HttpClientWatcher = HttpClientWatcher;
|