Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/common/http/src/transfer_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,17 @@ function getFilteredHeaders(
}

function sortAndConcatParams(params: HttpParams | URLSearchParams): string {
return [...params.keys()]
.sort()
.map((k) => `${k}=${params.getAll(k)}`)
.join('&');
const searchParams = new URLSearchParams(
params instanceof URLSearchParams ? params : params.toString(),
);
searchParams.sort();
return searchParams.toString();
}

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

Expand Down
41 changes: 40 additions & 1 deletion packages/common/http/test/transfer_cache_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ import {TestBed} from '@angular/core/testing';
import {useAutoTick, timeout, withBody} from '@angular/private/testing';
import {BehaviorSubject, Observable, of} from 'rxjs';

import {HttpClient, HttpHeaders, HttpRequest, HttpResponse, provideHttpClient} from '../public_api';
import {
HttpClient,
HttpHeaders,
HttpParams,
HttpRequest,
HttpResponse,
provideHttpClient,
} from '../public_api';
import {
BODY,
CACHE_OPTIONS,
Expand Down Expand Up @@ -432,6 +439,38 @@ describe('TransferCache', () => {
);
});

it('should differentiate repeated parameters from scalar comma parameters', () => {
let scalarResponse!: string;
TestBed.inject(HttpClient)
.get('/test-params', {params: new HttpParams().set('role', 'user,admin')})
.subscribe((response) => (scalarResponse = response as string));
TestBed.inject(HttpTestingController)
.expectOne('/test-params?role=user,admin')
.flush('scalar');

let repeatedResponse!: string;
TestBed.inject(HttpClient)
.get('/test-params', {
params: new HttpParams().append('role', 'user').append('role', 'admin'),
})
.subscribe((response) => (repeatedResponse = response as string));
TestBed.inject(HttpTestingController)
.expectOne('/test-params?role=user&role=admin')
.flush('repeated');

let repeatedCachedResponse!: string;
TestBed.inject(HttpClient)
.get('/test-params', {
params: new HttpParams().append('role', 'user').append('role', 'admin'),
})
.subscribe((response) => (repeatedCachedResponse = response as string));
TestBed.inject(HttpTestingController).expectNone('/test-params?role=user&role=admin');

expect(scalarResponse).toBe('scalar');
expect(repeatedResponse).toBe('repeated');
expect(repeatedCachedResponse).toBe('repeated');
});

it('should skip cache when specified', () => {
makeRequestAndExpectOne('/test-1?foo=1', 'foo', {transferCache: false});
// The previous request wasn't cached so this one can't use the cache
Expand Down
Loading