Ajax: Fix getResponseHeader(key) for IE11

- getResponseHeader(key) combines all header values for the provided key into a
single result where values are concatenated by ', '. This does not happen for
IE11 since multiple values for the same header are returned on separate lines.
This makes the function only return the last value of the header for IE11.
- Updated ajax headers test to better cover Object.prototype collisions

Close gh-4173
Fixes gh-3403
This commit is contained in:
Andrei Fangli 2018-11-26 19:00:41 +02:00 committed by Timmy Willison
parent 3ac907864c
commit e0d9411569
4 changed files with 16 additions and 5 deletions

View File

@ -459,12 +459,14 @@ jQuery.extend( {
if ( !responseHeaders ) { if ( !responseHeaders ) {
responseHeaders = {}; responseHeaders = {};
while ( ( match = rheaders.exec( responseHeadersString ) ) ) { while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
.concat( match[ 2 ] );
} }
} }
match = responseHeaders[ key.toLowerCase() ]; match = responseHeaders[ key.toLowerCase() + " " ];
} }
return match == null ? null : match; return match == null ? null : match.join( ", " );
}, },
// Raw string // Raw string

View File

@ -114,6 +114,9 @@ ok( true, "mock executed");';
header( 'Sample-Header: Hello World' ); header( 'Sample-Header: Hello World' );
header( 'Empty-Header: ' ); header( 'Empty-Header: ' );
header( 'Sample-Header2: Hello World 2' ); header( 'Sample-Header2: Hello World 2' );
header( 'List-Header: Item 1' );
header( 'list-header: Item 2' );
header( 'constructor: prototype collision (constructor)' );
foreach ( explode( '|' , $req->query[ 'keys' ] ) as $key ) { foreach ( explode( '|' , $req->query[ 'keys' ] ) as $key ) {
// Only echo if key exists in the header // Only echo if key exists in the header

View File

@ -132,7 +132,10 @@ var mocks = {
resp.writeHead( 200, { resp.writeHead( 200, {
"Sample-Header": "Hello World", "Sample-Header": "Hello World",
"Empty-Header": "", "Empty-Header": "",
"Sample-Header2": "Hello World 2" "Sample-Header2": "Hello World 2",
"List-Header": "Item 1",
"list-header": "Item 2",
"constructor": "prototype collision (constructor)"
} ); } );
req.query.keys.split( "|" ).forEach( function( key ) { req.query.keys.split( "|" ).forEach( function( key ) {
if ( req.headers[ key.toLowerCase() ] ) { if ( req.headers[ key.toLowerCase() ] ) {

View File

@ -252,7 +252,7 @@ QUnit.module( "ajax", {
} ); } );
} ); } );
ajaxTest( "jQuery.ajax() - headers", 5, function( assert ) { ajaxTest( "jQuery.ajax() - headers", 8, function( assert ) {
return { return {
setup: function() { setup: function() {
jQuery( document ).ajaxSend( function( evt, xhr ) { jQuery( document ).ajaxSend( function( evt, xhr ) {
@ -293,6 +293,9 @@ QUnit.module( "ajax", {
assert.strictEqual( emptyHeader, "", "Empty header received" ); assert.strictEqual( emptyHeader, "", "Empty header received" );
} }
assert.strictEqual( xhr.getResponseHeader( "Sample-Header2" ), "Hello World 2", "Second sample header received" ); assert.strictEqual( xhr.getResponseHeader( "Sample-Header2" ), "Hello World 2", "Second sample header received" );
assert.strictEqual( xhr.getResponseHeader( "List-Header" ), "Item 1, Item 2", "List header received" );
assert.strictEqual( xhr.getResponseHeader( "constructor" ), "prototype collision (constructor)", "constructor header received" );
assert.strictEqual( xhr.getResponseHeader( "__proto__" ), null, "Undefined __proto__ header not received" );
} }
}; };
} ); } );