Skip to content

Commit

Permalink
fix(http): return URL in Response
Browse files Browse the repository at this point in the history
Attach reponseURL or X-Request-URL to Response.

Closes  #5165
  • Loading branch information
robwormald committed Nov 23, 2015
1 parent 4332ccf commit 46fc153
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 4 deletions.
4 changes: 2 additions & 2 deletions modules/angular2/src/http/backends/jsonp_backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ 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);
}
responseObserver.error(new Response(responseOptions));
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);
}
Expand Down
6 changes: 4 additions & 2 deletions modules/angular2/src/http/backends/xhr_backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand All @@ -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);
}
Expand Down
10 changes: 10 additions & 0 deletions modules/angular2/src/http/http_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
38 changes: 38 additions & 0 deletions modules/angular2/test/http/backends/xhr_backend_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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); }
Expand Down Expand Up @@ -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');
}));
});
});
}

0 comments on commit 46fc153

Please sign in to comment.