fix(http): match header values exactly when deleting

Normalize value-specific HttpHeaders deletions before filtering. The string overload previously used String#indexOf and removed shorter values contained within the requested deletion value, potentially widening outgoing request metadata.

Preserve delete-all behavior only when no value is supplied, and cover string, array, and empty-string deletion.

(cherry picked from commit f33ee95045)
This commit is contained in:
SkyZeroZx
2026-07-16 16:53:40 -05:00
committed by Alex Rickabaugh
parent be46ca8696
commit 39e362eea5
2 changed files with 32 additions and 3 deletions
+4 -3
View File
@@ -223,16 +223,17 @@ export class HttpHeaders {
this.headers.set(key, base);
break;
case 'd':
const toDelete = update.value as string | undefined;
if (!toDelete) {
const toDelete = update.value;
if (toDelete === undefined) {
this.headers.delete(key);
this.normalizedNames.delete(key);
} else {
const valuesToDelete = Array.isArray(toDelete) ? toDelete : [toDelete];
let existing = this.headers.get(key);
if (!existing) {
return;
}
existing = existing.filter((value) => toDelete.indexOf(value) === -1);
existing = existing.filter((value) => valuesToDelete.indexOf(value) === -1);
if (existing.length === 0) {
this.headers.delete(key);
this.normalizedNames.delete(key);
+28
View File
@@ -154,6 +154,34 @@ describe('HttpHeaders', () => {
const fourth = third.delete('FOO');
expect(fourth.has('foo')).toEqual(false);
});
it('should delete only the exact matching string value', () => {
const headers = new HttpHeaders({
'X-Scopes': ['tenant:alpha', 'tenant:alpha:archive'],
});
const updated = headers.delete('X-Scopes', 'tenant:alpha:archive');
expect(updated.getAll('X-Scopes')).toEqual(['tenant:alpha']);
});
it('should delete only exact matching values from an array', () => {
const headers = new HttpHeaders({
'X-Scopes': ['tenant:alpha', 'tenant:alpha:archive'],
});
const updated = headers.delete('X-Scopes', ['tenant:alpha:archive']);
expect(updated.getAll('X-Scopes')).toEqual(['tenant:alpha']);
});
it('should treat an empty string as a value to delete', () => {
const headers = new HttpHeaders({foo: ['', 'bar']});
const updated = headers.delete('foo', '');
expect(updated.getAll('foo')).toEqual(['bar']);
});
});
describe('.append', () => {