X Tutup
Skip to content

Commit 4332ccf

Browse files
committed
fix(http): return Response headers
Properly parse and add response Headers to Response. Closes #5237
1 parent 201f189 commit 4332ccf

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

modules/angular2/src/http/backends/xhr_backend.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {ConnectionBackend, Connection} from '../interfaces';
22
import {ReadyStates, RequestMethods, ResponseTypes} from '../enums';
33
import {Request} from '../static_request';
44
import {Response} from '../static_response';
5+
import {Headers} from '../headers';
56
import {ResponseOptions, BaseResponseOptions} from '../base_response_options';
67
import {Injectable} from 'angular2/angular2';
78
import {BrowserXhr} from './browser_xhr';
@@ -34,8 +35,9 @@ export class XHRConnection implements Connection {
3435
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
3536
// response/responseType properties were introduced in XHR Level2 spec (supported by
3637
// IE10)
37-
let xhrResponse = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
38+
let body = isPresent(_xhr.response) ? _xhr.response : _xhr.responseText;
3839

40+
let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
3941

4042
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
4143
let status: number = _xhr.status === 1223 ? 204 : _xhr.status;
@@ -44,9 +46,9 @@ export class XHRConnection implements Connection {
4446
// Occurs when accessing file resources or on Android 4.1 stock browser
4547
// while retrieving files from application cache.
4648
if (status === 0) {
47-
status = xhrResponse ? 200 : 0;
49+
status = body ? 200 : 0;
4850
}
49-
var responseOptions = new ResponseOptions({body: xhrResponse, status: status});
51+
var responseOptions = new ResponseOptions({body, status, headers});
5052
if (isPresent(baseResponseOptions)) {
5153
responseOptions = baseResponseOptions.merge(responseOptions);
5254
}

modules/angular2/src/http/headers.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ export class Headers {
5454
headers, (v, k) => { this._headersMap.set(k, isListLikeIterable(v) ? v : [v]); });
5555
}
5656

57+
/**
58+
* Returns a new Headers instance from the given DOMString of Response Headers
59+
*/
60+
static fromResponseHeaderString(headersString: string): Headers {
61+
return headersString.trim()
62+
.split('\n')
63+
.map(val => val.split(':'))
64+
.map(([key, ...parts]) => ([key.trim(), parts.join(':').trim()]))
65+
.reduce((headers, [key, value]) => !headers.set(key, value) && headers, new Headers());
66+
}
67+
5768
/**
5869
* Appends a header to existing list of header values for a given header name.
5970
*/

modules/angular2/test/http/backends/xhr_backend_spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class MockBrowserXHR extends BrowserXhr {
4040
setRequestHeader: any;
4141
callbacks = new Map<string, Function>();
4242
status: number;
43+
responseHeaders: string;
4344
constructor() {
4445
super();
4546
var spy = new SpyObject();
@@ -55,6 +56,10 @@ class MockBrowserXHR extends BrowserXhr {
5556

5657
setResponseText(value) { this.responseText = value; }
5758

59+
setResponseHeaders(value) { this.responseHeaders = value; }
60+
61+
getAllResponseHeaders() { return this.responseHeaders || ''; }
62+
5863
addEventListener(type: string, cb: Function) { this.callbacks.set(type, cb); }
5964

6065
removeEventListener(type: string, cb: Function) { this.callbacks.delete(type); }
@@ -256,6 +261,30 @@ export function main() {
256261
existingXHRs[0].dispatchEvent('load');
257262
}));
258263

264+
it('should parse response headers and add them to the response',
265+
inject([AsyncTestCompleter], async => {
266+
var statusCode = 200;
267+
var connection = new XHRConnection(sampleRequest, new MockBrowserXHR(),
268+
new ResponseOptions({status: statusCode}));
269+
270+
let responseHeaderString =
271+
`Date: Fri, 20 Nov 2015 01:45:26 GMT
272+
Content-Type: application/json; charset=utf-8
273+
Transfer-Encoding: chunked
274+
Connection: keep-alive`
275+
276+
connection.response.subscribe(res => {
277+
expect(res.headers.get('Date')).toEqual('Fri, 20 Nov 2015 01:45:26 GMT');
278+
expect(res.headers.get('Content-Type')).toEqual('application/json; charset=utf-8');
279+
expect(res.headers.get('Transfer-Encoding')).toEqual('chunked');
280+
expect(res.headers.get('Connection')).toEqual('keep-alive');
281+
async.done();
282+
});
283+
284+
existingXHRs[0].setResponseHeaders(responseHeaderString);
285+
existingXHRs[0].setStatusCode(statusCode);
286+
existingXHRs[0].dispatchEvent('load');
287+
}));
259288
});
260289
});
261290
}

modules/angular2/test/http/headers_spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,23 @@ export function main() {
6363
});
6464
});
6565
});
66+
67+
describe('.fromResponseHeaderString()', () => {
68+
69+
it('should parse a response header string', () => {
70+
71+
let responseHeaderString = `Date: Fri, 20 Nov 2015 01:45:26 GMT
72+
Content-Type: application/json; charset=utf-8
73+
Transfer-Encoding: chunked
74+
Connection: keep-alive`;
75+
76+
let responseHeaders = Headers.fromResponseHeaderString(responseHeaderString);
77+
78+
expect(responseHeaders.get('Date')).toEqual('Fri, 20 Nov 2015 01:45:26 GMT');
79+
expect(responseHeaders.get('Content-Type')).toEqual('application/json; charset=utf-8');
80+
expect(responseHeaders.get('Transfer-Encoding')).toEqual('chunked');
81+
expect(responseHeaders.get('Connection')).toEqual('keep-alive');
82+
83+
});
84+
});
6685
}

0 commit comments

Comments
 (0)
X Tutup