@outputai/http 0.1.2 → 0.1.3-dev.0
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/config.d.ts +10 -0
- package/dist/config.js +10 -0
- package/dist/hooks/assign_request_id.d.ts +9 -0
- package/dist/hooks/assign_request_id.js +15 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/trace_error.d.ts +14 -0
- package/dist/hooks/trace_error.js +61 -0
- package/dist/hooks/trace_error.spec.d.ts +1 -0
- package/dist/hooks/trace_error.spec.js +35 -0
- package/dist/hooks/trace_request.d.ts +6 -0
- package/dist/hooks/trace_request.js +25 -0
- package/dist/hooks/trace_request.spec.d.ts +1 -0
- package/dist/hooks/trace_request.spec.js +60 -0
- package/dist/hooks/trace_response.d.ts +6 -0
- package/dist/hooks/trace_response.js +26 -0
- package/dist/hooks/trace_response.spec.d.ts +1 -0
- package/dist/hooks/trace_response.spec.js +68 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.integration.test.d.ts +1 -0
- package/dist/index.integration.test.js +389 -0
- package/dist/index.js +51 -0
- package/dist/index.spec.d.ts +1 -0
- package/dist/index.spec.js +391 -0
- package/dist/utils/create_trace_id.d.ts +13 -0
- package/dist/utils/create_trace_id.js +20 -0
- package/dist/utils/create_trace_id.spec.d.ts +1 -0
- package/dist/utils/create_trace_id.spec.js +20 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/parse_request_body.d.ts +7 -0
- package/dist/utils/parse_request_body.js +19 -0
- package/dist/utils/parse_request_body.spec.d.ts +1 -0
- package/dist/utils/parse_request_body.spec.js +19 -0
- package/dist/utils/parse_response_body.d.ts +10 -0
- package/dist/utils/parse_response_body.js +14 -0
- package/dist/utils/parse_response_body.spec.d.ts +1 -0
- package/dist/utils/parse_response_body.spec.js +19 -0
- package/dist/utils/redact_headers.d.ts +6 -0
- package/dist/utils/redact_headers.js +27 -0
- package/dist/utils/redact_headers.spec.d.ts +1 -0
- package/dist/utils/redact_headers.spec.js +245 -0
- package/package.json +2 -2
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import redactHeaders from './redact_headers.js';
|
|
3
|
+
describe('redactHeaders', () => {
|
|
4
|
+
describe('with Record<string, string> input', () => {
|
|
5
|
+
it('should redact sensitive headers (case insensitive)', () => {
|
|
6
|
+
const headers = {
|
|
7
|
+
Authorization: 'Bearer token123',
|
|
8
|
+
'X-API-Key': 'secret-key',
|
|
9
|
+
apikey: 'another-secret',
|
|
10
|
+
'X-Auth-Token': 'auth-token',
|
|
11
|
+
'Secret-Header': 'top-secret',
|
|
12
|
+
Password: 'password123',
|
|
13
|
+
'Private-Key': 'private-key-data',
|
|
14
|
+
Cookie: 'session=abc123',
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
'User-Agent': 'test-agent'
|
|
17
|
+
};
|
|
18
|
+
const result = redactHeaders(headers);
|
|
19
|
+
expect(result).toEqual({
|
|
20
|
+
Authorization: '[REDACTED]',
|
|
21
|
+
'X-API-Key': '[REDACTED]',
|
|
22
|
+
apikey: '[REDACTED]',
|
|
23
|
+
'X-Auth-Token': '[REDACTED]',
|
|
24
|
+
'Secret-Header': '[REDACTED]',
|
|
25
|
+
Password: '[REDACTED]',
|
|
26
|
+
'Private-Key': '[REDACTED]',
|
|
27
|
+
Cookie: '[REDACTED]',
|
|
28
|
+
'Content-Type': 'application/json',
|
|
29
|
+
'User-Agent': 'test-agent'
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it('should handle mixed case header names', () => {
|
|
33
|
+
const headers = {
|
|
34
|
+
AUTHORIZATION: 'Bearer token',
|
|
35
|
+
'x-api-key': 'secret',
|
|
36
|
+
'Api-Key': 'another-secret',
|
|
37
|
+
'TOKEN-HEADER': 'token-value',
|
|
38
|
+
'content-type': 'application/json'
|
|
39
|
+
};
|
|
40
|
+
const result = redactHeaders(headers);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
AUTHORIZATION: '[REDACTED]',
|
|
43
|
+
'x-api-key': '[REDACTED]',
|
|
44
|
+
'Api-Key': '[REDACTED]',
|
|
45
|
+
'TOKEN-HEADER': '[REDACTED]',
|
|
46
|
+
'content-type': 'application/json'
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
it('should not redact non-sensitive headers', () => {
|
|
50
|
+
const headers = {
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
Accept: 'application/json',
|
|
53
|
+
'User-Agent': 'test-agent',
|
|
54
|
+
'X-Custom-Header': 'custom-value',
|
|
55
|
+
'Cache-Control': 'no-cache'
|
|
56
|
+
};
|
|
57
|
+
const result = redactHeaders(headers);
|
|
58
|
+
expect(result).toEqual(headers);
|
|
59
|
+
});
|
|
60
|
+
it('should handle empty headers object', () => {
|
|
61
|
+
const headers = {};
|
|
62
|
+
const result = redactHeaders(headers);
|
|
63
|
+
expect(result).toEqual({});
|
|
64
|
+
});
|
|
65
|
+
it('should handle headers with empty values', () => {
|
|
66
|
+
const headers = {
|
|
67
|
+
Authorization: '',
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
'X-API-Key': ''
|
|
70
|
+
};
|
|
71
|
+
const result = redactHeaders(headers);
|
|
72
|
+
expect(result).toEqual({
|
|
73
|
+
Authorization: '[REDACTED]',
|
|
74
|
+
'Content-Type': 'application/json',
|
|
75
|
+
'X-API-Key': '[REDACTED]'
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('with Headers object input', () => {
|
|
80
|
+
it('should redact sensitive headers from Headers object', () => {
|
|
81
|
+
const headers = new Headers();
|
|
82
|
+
headers.set('Authorization', 'Bearer token123');
|
|
83
|
+
headers.set('X-API-Key', 'secret-key');
|
|
84
|
+
headers.set('Content-Type', 'application/json');
|
|
85
|
+
headers.set('User-Agent', 'test-agent');
|
|
86
|
+
const result = redactHeaders(headers);
|
|
87
|
+
expect(result).toEqual({
|
|
88
|
+
authorization: '[REDACTED]',
|
|
89
|
+
'x-api-key': '[REDACTED]',
|
|
90
|
+
'content-type': 'application/json',
|
|
91
|
+
'user-agent': 'test-agent'
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
it('should handle empty Headers object', () => {
|
|
95
|
+
const headers = new Headers();
|
|
96
|
+
const result = redactHeaders(headers);
|
|
97
|
+
expect(result).toEqual({});
|
|
98
|
+
});
|
|
99
|
+
it('should preserve header name casing from Headers object', () => {
|
|
100
|
+
const headers = new Headers();
|
|
101
|
+
headers.set('authorization', 'Bearer token');
|
|
102
|
+
headers.set('X-Custom-Header', 'value');
|
|
103
|
+
const result = redactHeaders(headers);
|
|
104
|
+
expect(result).toEqual({
|
|
105
|
+
authorization: '[REDACTED]',
|
|
106
|
+
'x-custom-header': 'value'
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('sensitive header patterns', () => {
|
|
111
|
+
it('should redact headers containing "authorization"', () => {
|
|
112
|
+
const headers = {
|
|
113
|
+
Authorization: 'Bearer token',
|
|
114
|
+
'X-Authorization': 'token',
|
|
115
|
+
'Custom-Authorization-Header': 'value'
|
|
116
|
+
};
|
|
117
|
+
const result = redactHeaders(headers);
|
|
118
|
+
Object.keys(result).forEach(key => {
|
|
119
|
+
if (key.toLowerCase().includes('authorization')) {
|
|
120
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
it('should redact headers containing "token"', () => {
|
|
125
|
+
const headers = {
|
|
126
|
+
'X-Auth-Token': 'token123',
|
|
127
|
+
'Access-Token': 'access123',
|
|
128
|
+
'Refresh-Token': 'refresh123',
|
|
129
|
+
'Token-Header': 'token-value'
|
|
130
|
+
};
|
|
131
|
+
const result = redactHeaders(headers);
|
|
132
|
+
Object.keys(result).forEach(key => {
|
|
133
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
it('should redact headers containing "api-key" or "apikey"', () => {
|
|
137
|
+
const headers = {
|
|
138
|
+
'X-API-Key': 'key123',
|
|
139
|
+
'X-Api-Key': 'key456',
|
|
140
|
+
apikey: 'key789',
|
|
141
|
+
'Custom-ApiKey': 'custom-key'
|
|
142
|
+
};
|
|
143
|
+
const result = redactHeaders(headers);
|
|
144
|
+
Object.keys(result).forEach(key => {
|
|
145
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
it('should redact headers containing "secret"', () => {
|
|
149
|
+
const headers = {
|
|
150
|
+
'X-Secret': 'secret123',
|
|
151
|
+
'Client-Secret': 'client-secret',
|
|
152
|
+
'Secret-Key': 'secret-key'
|
|
153
|
+
};
|
|
154
|
+
const result = redactHeaders(headers);
|
|
155
|
+
Object.keys(result).forEach(key => {
|
|
156
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
it('should redact headers containing "password"', () => {
|
|
160
|
+
const headers = {
|
|
161
|
+
Password: 'pass123',
|
|
162
|
+
'X-Password': 'secret-pass',
|
|
163
|
+
'User-Password': 'user-pass'
|
|
164
|
+
};
|
|
165
|
+
const result = redactHeaders(headers);
|
|
166
|
+
Object.keys(result).forEach(key => {
|
|
167
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
it('should redact headers containing "key"', () => {
|
|
171
|
+
const headers = {
|
|
172
|
+
'Private-Key': 'private123',
|
|
173
|
+
'Public-Key': 'public123',
|
|
174
|
+
'Encryption-Key': 'encrypt123',
|
|
175
|
+
'Symmetric-Key': 'sym123'
|
|
176
|
+
};
|
|
177
|
+
const result = redactHeaders(headers);
|
|
178
|
+
Object.keys(result).forEach(key => {
|
|
179
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
it('should redact headers containing "cookie"', () => {
|
|
183
|
+
const headers = {
|
|
184
|
+
Cookie: 'session=abc123',
|
|
185
|
+
'Set-Cookie': 'token=xyz789',
|
|
186
|
+
'X-Cookie-Data': 'cookie-info'
|
|
187
|
+
};
|
|
188
|
+
const result = redactHeaders(headers);
|
|
189
|
+
Object.keys(result).forEach(key => {
|
|
190
|
+
expect(result[key]).toBe('[REDACTED]');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe('edge cases', () => {
|
|
195
|
+
it('should handle headers with special characters in values', () => {
|
|
196
|
+
const headers = {
|
|
197
|
+
Authorization: 'Bearer !@#$%^&*()_+-=[]{}|;:,.<>?',
|
|
198
|
+
'Content-Type': 'application/json; charset=utf-8'
|
|
199
|
+
};
|
|
200
|
+
const result = redactHeaders(headers);
|
|
201
|
+
expect(result).toEqual({
|
|
202
|
+
Authorization: '[REDACTED]',
|
|
203
|
+
'Content-Type': 'application/json; charset=utf-8'
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
it('should handle headers with unicode characters', () => {
|
|
207
|
+
const headers = {
|
|
208
|
+
'X-API-Key': '🔑secret-key🔐',
|
|
209
|
+
'X-Custom': 'héllo wörld'
|
|
210
|
+
};
|
|
211
|
+
const result = redactHeaders(headers);
|
|
212
|
+
expect(result).toEqual({
|
|
213
|
+
'X-API-Key': '[REDACTED]',
|
|
214
|
+
'X-Custom': 'héllo wörld'
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
it('should handle very long header values', () => {
|
|
218
|
+
const longValue = 'a'.repeat(10000);
|
|
219
|
+
const headers = {
|
|
220
|
+
Authorization: `Bearer ${longValue}`,
|
|
221
|
+
'X-Long-Header': longValue
|
|
222
|
+
};
|
|
223
|
+
const result = redactHeaders(headers);
|
|
224
|
+
expect(result).toEqual({
|
|
225
|
+
Authorization: '[REDACTED]',
|
|
226
|
+
'X-Long-Header': longValue
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
it('should match partial words in header names (current behavior)', () => {
|
|
230
|
+
const headers = {
|
|
231
|
+
Keyboard: 'qwerty', // contains "key" - will be redacted
|
|
232
|
+
Secretary: 'admin', // contains "secret" - will be redacted
|
|
233
|
+
Tokens: 'abc123', // contains "token" - will be redacted
|
|
234
|
+
'Content-Length': '123' // doesn't contain sensitive patterns - will not be redacted
|
|
235
|
+
};
|
|
236
|
+
const result = redactHeaders(headers);
|
|
237
|
+
expect(result).toEqual({
|
|
238
|
+
Keyboard: '[REDACTED]',
|
|
239
|
+
Secretary: '[REDACTED]',
|
|
240
|
+
Tokens: '[REDACTED]',
|
|
241
|
+
'Content-Length': '123'
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outputai/http",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3-dev.0",
|
|
4
4
|
"description": "Framework abstraction to make HTTP calls with tracing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
],
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"ky": "1.14.3",
|
|
13
|
-
"@outputai/core": "0.1.
|
|
13
|
+
"@outputai/core": "0.1.3-dev.0"
|
|
14
14
|
},
|
|
15
15
|
"license": "Apache-2.0",
|
|
16
16
|
"publishConfig": {
|