Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.

Commit f09c51d

Browse files
Fabian WilesCaerusKaru
authored andcommitted
feat(common): TransferHttpCache now respects url params (#1005)
1 parent eaa3ea6 commit f09c51d

5 files changed

Lines changed: 69 additions & 8 deletions

File tree

modules/common/engine/private_api.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8+
89
export { FileLoader as ɵFileLoader, CommonEngine as ɵCommonEngine,
9-
RenderOptions as ɵRenderOptions } from './src/index';
10+
RenderOptions as ɵRenderOptions } from './src/index';

modules/common/private_api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
export { TransferHttpCacheInterceptor as ɵTransferHttpCacheInterceptor } from './src/transfer_http';

modules/common/public_api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
*/
88
export { TransferHttpCacheModule } from './src/transfer_http';
99
export { StateTransferInitializerModule } from './src/state-transfer-initializer/module';
10-
10+
export * from './private_api';
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { ɵTransferHttpCacheInterceptor as TransferHttpCacheInterceptor } from '@nguniversal/common';
2+
import { of } from 'rxjs';
3+
import { HttpParams } from '@angular/common/http';
4+
5+
function mockAppRef(): any {
6+
return {
7+
isStable: of(true)
8+
};
9+
}
10+
11+
function mockTransferState(): any {
12+
return {
13+
store: {}
14+
};
15+
}
16+
17+
describe('TransferHttp', () => {
18+
describe('keys', () => {
19+
it('should encode url params', () => {
20+
const interceptor = new TransferHttpCacheInterceptor(mockAppRef(), mockTransferState());
21+
const key = interceptor['makeCacheKey']('GET', 'https://google.com/api',
22+
new HttpParams().append('foo', 'bar'));
23+
expect(key).toEqual('G.https://google.com/api?foo=bar');
24+
});
25+
it('should sort the keys by unicode points', () => {
26+
const interceptor = new TransferHttpCacheInterceptor(mockAppRef(), mockTransferState());
27+
const key = interceptor['makeCacheKey']('GET', 'https://google.com/api',
28+
new HttpParams().append('b', 'foo').append('a', 'bar'));
29+
expect(key).toEqual('G.https://google.com/api?a=bar&b=foo');
30+
});
31+
it('should make equal keys if order of params changes', () => {
32+
const interceptor = new TransferHttpCacheInterceptor(mockAppRef(), mockTransferState());
33+
const key1 = interceptor['makeCacheKey']('GET', 'https://google.com/api',
34+
new HttpParams().append('a', 'bar').append('b', 'foo'));
35+
const key2 = interceptor['makeCacheKey']('GET', 'https://google.com/api',
36+
new HttpParams().append('b', 'foo').append('a', 'bar'));
37+
expect(key1).toEqual(key2);
38+
});
39+
});
40+
});

modules/common/src/transfer_http.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ import {
1212
HttpHeaders,
1313
HttpInterceptor,
1414
HttpRequest,
15-
HttpResponse
15+
HttpResponse,
16+
HttpParams
1617
} from '@angular/common/http';
1718
import {ApplicationRef, Injectable, NgModule} from '@angular/core';
18-
import {BrowserTransferStateModule, TransferState, makeStateKey} from '@angular/platform-browser';
19+
import {
20+
BrowserTransferStateModule,
21+
TransferState,
22+
makeStateKey,
23+
StateKey
24+
} from '@angular/platform-browser';
1925
import {Observable, of as observableOf} from 'rxjs';
2026
import {tap, take, filter} from 'rxjs/operators';
2127

@@ -41,8 +47,15 @@ export class TransferHttpCacheInterceptor implements HttpInterceptor {
4147
private isCacheActive = true;
4248

4349
private invalidateCacheEntry(url: string) {
44-
this.transferState.remove(makeStateKey<TransferHttpResponse>('G.' + url));
45-
this.transferState.remove(makeStateKey<TransferHttpResponse>('H.' + url));
50+
Object.keys(this.transferState['store'])
51+
.forEach(key => key.includes(url) ? this.transferState.remove(makeStateKey(key)) : null);
52+
}
53+
54+
private makeCacheKey(method: string, url: string, params: HttpParams): StateKey<string> {
55+
// make the params encoded same as a url so it's easy to identify
56+
const encodedParams = params.keys().sort().map(k => `${k}=${params.get(k)}`).join('&');
57+
const key = (method === 'GET' ? 'G.' : 'H.') + url + '?' + encodedParams;
58+
return makeStateKey<TransferHttpResponse>(key);
4659
}
4760

4861
constructor(appRef: ApplicationRef, private transferState: TransferState) {
@@ -68,8 +81,7 @@ export class TransferHttpCacheInterceptor implements HttpInterceptor {
6881
return next.handle(req);
6982
}
7083

71-
const key = (req.method === 'GET' ? 'G.' : 'H.') + req.url;
72-
const storeKey = makeStateKey<TransferHttpResponse>(key);
84+
const storeKey = this.makeCacheKey(req.method, req.url, req.params);
7385

7486
if (this.transferState.hasKey(storeKey)) {
7587
// Request found in cache. Respond using it.

0 commit comments

Comments
 (0)