Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a64e288

Browse files
Hexix23alxhub
authored andcommitted
fix(http): distinguish repeated transfer cache params
Serialize transfer cache request parameters without comma-joining repeated values so distinct HttpClient requests cannot reuse the same cached response.
1 parent 5dbcd0e commit a64e288

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,17 +313,17 @@ function getFilteredHeaders(
313313
}
314314

315315
function sortAndConcatParams(params: HttpParams | URLSearchParams): string {
316-
return [...params.keys()]
317-
.sort()
318-
.map((k) => `${k}=${params.getAll(k)}`)
319-
.join('&');
316+
const searchParams = new URLSearchParams(
317+
params instanceof URLSearchParams ? params : params.toString(),
318+
);
319+
searchParams.sort();
320+
return searchParams.toString();
320321
}
321322

322323
function makeCacheKey(
323324
request: HttpRequest<any>,
324325
mappedRequestUrl: string,
325326
): StateKey<TransferHttpResponse> {
326-
// make the params encoded same as a url so it's easy to identify
327327
const {params, method, responseType} = request;
328328
const encodedParams = sortAndConcatParams(params);
329329

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ import {fakeAsync, flush, TestBed} from '@angular/core/testing';
1919
import {withBody} from '@angular/private/testing';
2020
import {BehaviorSubject, Observable, of} from 'rxjs';
2121

22-
import {HttpClient, HttpHeaders, HttpRequest, HttpResponse, provideHttpClient} from '../public_api';
22+
import {
23+
HttpClient,
24+
HttpHeaders,
25+
HttpParams,
26+
HttpRequest,
27+
HttpResponse,
28+
provideHttpClient,
29+
} from '../public_api';
2330
import {
2431
BODY,
2532
CACHE_OPTIONS,
@@ -426,6 +433,38 @@ describe('TransferCache', () => {
426433
);
427434
});
428435

436+
it('should differentiate repeated parameters from scalar comma parameters', () => {
437+
let scalarResponse!: string;
438+
TestBed.inject(HttpClient)
439+
.get('/test-params', {params: new HttpParams().set('role', 'user,admin')})
440+
.subscribe((response) => (scalarResponse = response as string));
441+
TestBed.inject(HttpTestingController)
442+
.expectOne('/test-params?role=user,admin')
443+
.flush('scalar');
444+
445+
let repeatedResponse!: string;
446+
TestBed.inject(HttpClient)
447+
.get('/test-params', {
448+
params: new HttpParams().append('role', 'user').append('role', 'admin'),
449+
})
450+
.subscribe((response) => (repeatedResponse = response as string));
451+
TestBed.inject(HttpTestingController)
452+
.expectOne('/test-params?role=user&role=admin')
453+
.flush('repeated');
454+
455+
let repeatedCachedResponse!: string;
456+
TestBed.inject(HttpClient)
457+
.get('/test-params', {
458+
params: new HttpParams().append('role', 'user').append('role', 'admin'),
459+
})
460+
.subscribe((response) => (repeatedCachedResponse = response as string));
461+
TestBed.inject(HttpTestingController).expectNone('/test-params?role=user&role=admin');
462+
463+
expect(scalarResponse).toBe('scalar');
464+
expect(repeatedResponse).toBe('repeated');
465+
expect(repeatedCachedResponse).toBe('repeated');
466+
});
467+
429468
it('should skip cache when specified', () => {
430469
makeRequestAndExpectOne('/test-1?foo=1', 'foo', {transferCache: false});
431470
// The previous request wasn't cached so this one can't use the cache

0 commit comments

Comments
 (0)