Skip to content

Commit ffca153

Browse files
committed
fix(http): include query params in the XHR backend fallback URL
When the browser did not provide a response URL, as happens on network errors and timeouts, HttpXhrBackend fell back on `req.url`, which leaves out the query params. So `HttpErrorResponse.url` and its message showed `/api/items` for a request to `/api/items?page=2`. Fall back on `req.urlWithParams`, which is the URL the request was sent to and what FetchBackend already uses.
1 parent 4044cef commit ffca153

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

‎packages/common/http/src/xhr.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export class HttpXhrBackend implements HttpBackend {
219219

220220
// Read the response URL from the XMLHttpResponse instance and fall back on the
221221
// request URL.
222-
const url = xhr.responseURL || req.url;
222+
const url = xhr.responseURL || req.urlWithParams;
223223

224224
// Construct the HttpHeaderResponse and memoize it.
225225
headerResponse = new HttpHeaderResponse({headers, status: xhr.status, statusText, url});

‎packages/common/http/test/xhr_spec.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {TestBed} from '@angular/core/testing';
1010
import {Observable} from 'rxjs';
1111
import {toArray} from 'rxjs/operators';
1212
import {XhrFactory} from '../../index';
13+
import {HttpParams} from '../src/params';
1314
import {HttpRequest} from '../src/request';
1415
import {
1516
HttpDownloadProgressEvent,
@@ -425,6 +426,29 @@ describe('XhrBackend', () => {
425426
factory.mock.responseURL = '/response/url';
426427
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Test');
427428
});
429+
it('falls back on the request URL with params', (done) => {
430+
backend
431+
.handle(TEST_POST.clone({params: new HttpParams({fromObject: {page: '2'}})}))
432+
.pipe(toArray())
433+
.subscribe((events) => {
434+
const response = events[1] as HttpResponse<string>;
435+
expect(response.url).toBe('/test?page=2');
436+
done();
437+
});
438+
factory.mock.mockFlush(HttpStatusCode.Ok, 'OK', 'Test');
439+
});
440+
it('includes the params in the URL of a network error', (done) => {
441+
backend
442+
.handle(TEST_POST.clone({params: new HttpParams({fromObject: {page: '2'}})}))
443+
.subscribe({
444+
error: (err: HttpErrorResponse) => {
445+
expect(err.url).toBe('/test?page=2');
446+
expect(err.message).toContain('/test?page=2');
447+
done();
448+
},
449+
});
450+
factory.mock.mockErrorEvent(new Error('blah'));
451+
});
428452
it('falls back on Request.url if neither are available', (done) => {
429453
backend
430454
.handle(TEST_POST)

0 commit comments

Comments
 (0)