fix(http): return URL in Response

Attach reponseURL or X-Request-URL to Response.

Closes  #5165
This commit is contained in:
Rob Wormald 2015-11-19 18:47:29 -08:00
parent 4332ccf72c
commit 46fc153f39
4 changed files with 54 additions and 4 deletions

View File

@ -57,7 +57,7 @@ export class JSONPConnection_ extends JSONPConnection {
_dom.cleanup(script);
if (!this._finished) {
let responseOptions =
new ResponseOptions({body: JSONP_ERR_NO_CALLBACK, type: ResponseTypes.Error});
new ResponseOptions({body: JSONP_ERR_NO_CALLBACK, type: ResponseTypes.Error, url});
if (isPresent(baseResponseOptions)) {
responseOptions = baseResponseOptions.merge(responseOptions);
}
@ -65,7 +65,7 @@ export class JSONPConnection_ extends JSONPConnection {
return;
}
let responseOptions = new ResponseOptions({body: this._responseData});
let responseOptions = new ResponseOptions({body: this._responseData, url});
if (isPresent(this.baseResponseOptions)) {
responseOptions = this.baseResponseOptions.merge(responseOptions);
}

View File

@ -8,7 +8,7 @@ import {Injectable} from 'angular2/angular2';
import {BrowserXhr} from './browser_xhr';
import {isPresent} from 'angular2/src/facade/lang';
import {Observable} from 'angular2/angular2';
import {isSuccess} from '../http_utils';
import {isSuccess, getResponseURL} from '../http_utils';
/**
* Creates connections using `XMLHttpRequest`. Given a fully-qualified
* request, an `XHRConnection` will immediately create an `XMLHttpRequest` object and send the
@ -39,6 +39,8 @@ export class XHRConnection implements Connection {
let headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders());
let url = getResponseURL(_xhr);
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
let status: number = _xhr.status === 1223 ? 204 : _xhr.status;
@ -48,7 +50,7 @@ export class XHRConnection implements Connection {
if (status === 0) {
status = body ? 200 : 0;
}
var responseOptions = new ResponseOptions({body, status, headers});
var responseOptions = new ResponseOptions({body, status, headers, url});
if (isPresent(baseResponseOptions)) {
responseOptions = baseResponseOptions.merge(responseOptions);
}

View File

@ -17,4 +17,14 @@ export function normalizeMethodName(method): RequestMethods {
export const isSuccess = (status: number): boolean => (status >= 200 && status < 300);
export function getResponseURL(xhr: any): string {
if ('responseURL' in xhr) {
return xhr.responseURL;
}
if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
return xhr.getResponseHeader('X-Request-URL');
}
return;
}
export {isJsObject} from 'angular2/src/facade/lang';

View File

@ -41,6 +41,7 @@ class MockBrowserXHR extends BrowserXhr {
callbacks = new Map<string, Function>();
status: number;
responseHeaders: string;
responseURL: string;
constructor() {
super();
var spy = new SpyObject();
@ -56,10 +57,14 @@ class MockBrowserXHR extends BrowserXhr {
setResponseText(value) { this.responseText = value; }
setResponseURL(value) { this.responseURL = value; }
setResponseHeaders(value) { this.responseHeaders = value; }
getAllResponseHeaders() { return this.responseHeaders || ''; }
getResponseHeader(key) { return Headers.fromResponseHeaderString(this.responseHeaders).get(key); }
addEventListener(type: string, cb: Function) { this.callbacks.set(type, cb); }
removeEventListener(type: string, cb: Function) { this.callbacks.delete(type); }
@ -285,6 +290,39 @@ export function main() {
existingXHRs[0].setStatusCode(statusCode);
existingXHRs[0].dispatchEvent('load');
}));
it('should add the responseURL to the response', inject([AsyncTestCompleter], async => {
var statusCode = 200;
var connection = new XHRConnection(sampleRequest, new MockBrowserXHR(),
new ResponseOptions({status: statusCode}));
connection.response.subscribe(res => {
expect(res.url).toEqual('http://google.com');
async.done();
});
existingXHRs[0].setResponseURL('http://google.com');
existingXHRs[0].setStatusCode(statusCode);
existingXHRs[0].dispatchEvent('load');
}));
it('should add use the X-Request-URL in CORS situations',
inject([AsyncTestCompleter], async => {
var statusCode = 200;
var connection = new XHRConnection(sampleRequest, new MockBrowserXHR(),
new ResponseOptions({status: statusCode}));
var responseHeaders = `X-Request-URL: http://somedomain.com
Foo: Bar`
connection.response.subscribe(res => {
expect(res.url).toEqual('http://somedomain.com');
async.done();
});
existingXHRs[0].setResponseHeaders(responseHeaders);
existingXHRs[0].setStatusCode(statusCode);
existingXHRs[0].dispatchEvent('load');
}));
});
});
}