Global Request Headers allows developers to inject, override, or remove HTTP headers on all outgoing requests without code changes. This feature is perfect for:
Settings Panel: Global Request Headers
add, override, remove{
key: 'Authorization', // Header name
value: 'Bearer token-123', // Header value (not needed for 'remove')
mode: 'override', // 'add' | 'override' | 'remove'
urlPattern: '/api', // Optional URL filter (blank = all)
enabled: true // Enable/disable toggle
}
/api matches /api/users, /api/products, etc..com/v2 matches api.example.com/v2/endpointextension/background.jsrequestHeaders: [] to default settingspushTabMeta() to send requestHeaders to tabsextension/shared/app.jsrequestHeaders: [] to state initializationextension/injected.jsstate.requestHeaders to receive rules from backgroundapplyRequestHeaders(headers, url) functiontests/smoke_echokit.pymemory/PRD.mdUser configures in Settings
↓
Background service worker stores in chrome.storage.local
↓
Injected script receives state update via postMessage
↓
applyRequestHeaders() modifies headers
↓
fetch/XHR executes with modified headers
↓
Modified headers are recorded in interactions
// In injected.js
function applyRequestHeaders(headers, url) {
const rules = (state.requestHeaders || []).filter(r => r.enabled !== false);
if (!rules.length) return headers;
let modified = { ...headers };
for (const rule of rules) {
// URL pattern filtering
if (rule.urlPattern && !url.includes(rule.urlPattern)) continue;
const key = rule.key || '';
if (!key) continue;
if (rule.mode === 'add') {
// Only add if header doesn't exist
if (!(key in modified)) {
modified[key] = rule.value || '';
}
} else if (rule.mode === 'override' || !rule.mode) {
// Set header (default mode)
modified[key] = rule.value || '';
} else if (rule.mode === 'remove') {
// Delete header
delete modified[key];
}
}
return modified;
}
{
"key": "Authorization",
"value": "Bearer eyJhbGciOiJIUzI1NiIs...",
"mode": "override",
"urlPattern": "/api",
"enabled": true
}
Result: All requests to URLs containing “/api” will have this Authorization header.
[
{
"key": "X-Tenant-ID",
"value": "tenant-a",
"mode": "override",
"urlPattern": "",
"enabled": true
},
{
"key": "X-Tenant-ID",
"value": "tenant-b",
"mode": "override",
"urlPattern": "",
"enabled": false
}
]
Usage: Toggle between tenants by enabling/disabling rules.
{
"key": "X-Feature-Flags",
"value": "new-checkout,beta-ui",
"mode": "add",
"urlPattern": "",
"enabled": true
}
Result: Adds feature flag header to all requests (only if app doesn’t already send it).
[
{
"key": "X-Client-ID",
"mode": "remove",
"enabled": true
},
{
"key": "X-Session-ID",
"mode": "remove",
"enabled": true
}
]
Result: Strips tracking headers from all requests for clean testing.
mode: 'override' → Verify it appears in DevTools Network tabmode: 'add' → Verify it only adds if not presentmode: 'remove' → Verify header is strippedRun: python3 tests/smoke_echokit.py
Test validates:
requestHeaders defaults to empty array []requestHeaders) import cleanlyrequestHeaders) are backward-compatibleechokit-server --request-headersoverride (not add)See additional documentation in /memory/:
FEATURE_GLOBAL_REQUEST_HEADERS.md - Full technical specIMPLEMENTATION_GUIDE_REQUEST_HEADERS.md - Code implementation guideDEVELOPER_CONFIG_EXAMPLES.md - Real-world examplesPRODUCT_STRATEGY_ROLLOUT.md - Product strategyQUICK_REFERENCE.md - User quick start guideVersion: 1.7.0
Released: [Date TBD]
Status: ✅ Ready for PR