Skip to content

Commit b2415c4

Browse files
ascherkusfacebook-github-bot
authored andcommitted
Update XMLHttpRequest.getAllResponseHeaders() implementation (#32353) (#32363)
Summary: As per the XMLHttpRequest specification [1], getAllResponseHeaders() should return a string of headers with lowercased names and sorted by their uppercase representation, with each header ending with '\r\n'. [1] https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method ## Changelog [General] [Changed] XMLHttpRequest.getAllResponseHeaders() now returns headers with names lowercased and sorted in ascending order, as per specification Pull Request resolved: #32363 Test Plan: Test derived from Web Platform Test repository: https://github.com/web-platform-tests/wpt/tree/master/xhr Reviewed By: yungsters Differential Revision: D31626217 Pulled By: sota000 fbshipit-source-id: 299d005facbe1c15b8cda5eed6750db75addca80
1 parent 65af5eb commit b2415c4

File tree

2 files changed

+62
-7
lines changed

2 files changed

+62
-7
lines changed

Libraries/Network/XMLHttpRequest.js

+43-6
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,49 @@ class XMLHttpRequest extends (EventTarget(...XHR_EVENTS): any) {
423423
// according to the spec, return null if no response has been received
424424
return null;
425425
}
426-
const headers = this.responseHeaders || {};
427-
return Object.keys(headers)
428-
.map(headerName => {
429-
return headerName + ': ' + headers[headerName];
430-
})
431-
.join('\r\n');
426+
427+
// Assign to non-nullable local variable.
428+
const responseHeaders = this.responseHeaders;
429+
430+
const unsortedHeaders: Map<
431+
string,
432+
{lowerHeaderName: string, upperHeaderName: string, headerValue: string},
433+
> = new Map();
434+
for (const rawHeaderName of Object.keys(responseHeaders)) {
435+
const headerValue = responseHeaders[rawHeaderName];
436+
const lowerHeaderName = rawHeaderName.toLowerCase();
437+
const header = unsortedHeaders.get(lowerHeaderName);
438+
if (header) {
439+
header.headerValue += ', ' + headerValue;
440+
unsortedHeaders.set(lowerHeaderName, header);
441+
} else {
442+
unsortedHeaders.set(lowerHeaderName, {
443+
lowerHeaderName,
444+
upperHeaderName: rawHeaderName.toUpperCase(),
445+
headerValue,
446+
});
447+
}
448+
}
449+
450+
// Sort in ascending order, with a being less than b if a's name is legacy-uppercased-byte less than b's name.
451+
const sortedHeaders = [...unsortedHeaders.values()].sort((a, b) => {
452+
if (a.upperHeaderName < b.upperHeaderName) {
453+
return -1;
454+
}
455+
if (a.upperHeaderName > b.upperHeaderName) {
456+
return 1;
457+
}
458+
return 0;
459+
});
460+
461+
// Combine into single text response.
462+
return (
463+
sortedHeaders
464+
.map(header => {
465+
return header.lowerHeaderName + ': ' + header.headerValue;
466+
})
467+
.join('\r\n') + '\r\n'
468+
);
432469
}
433470

434471
getResponseHeader(header: string): ?string {

Libraries/Network/__tests__/XMLHttpRequest-test.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ describe('XMLHttpRequest', function() {
241241
});
242242

243243
expect(xhr.getAllResponseHeaders()).toBe(
244-
'Content-Type: text/plain; charset=utf-8\r\n' + 'Content-Length: 32',
244+
'content-length: 32\r\n' + 'content-type: text/plain; charset=utf-8\r\n',
245245
);
246246
});
247247

@@ -292,4 +292,22 @@ describe('XMLHttpRequest', function() {
292292
);
293293
expect(GlobalPerformanceLogger.stopTimespan).not.toHaveBeenCalled();
294294
});
295+
296+
it('should sort and lowercase response headers', function() {
297+
// Derived from XHR Web Platform Test: https://github.com/web-platform-tests/wpt/blob/master/xhr/getallresponseheaders.htm
298+
xhr.open('GET', 'blabla');
299+
xhr.send();
300+
setRequestId(10);
301+
xhr.__didReceiveResponse(requestId, 200, {
302+
'foo-TEST': '1',
303+
'FOO-test': '2',
304+
__Custom: 'token',
305+
'ALSO-here': 'Mr. PB',
306+
ewok: 'lego',
307+
});
308+
309+
expect(xhr.getAllResponseHeaders()).toBe(
310+
'also-here: Mr. PB\r\newok: lego\r\nfoo-test: 1, 2\r\n__custom: token\r\n',
311+
);
312+
});
295313
});

0 commit comments

Comments
 (0)