Skip to content

Commit

Permalink
fix(common): skip transfer cache on client (#55012)
Browse files Browse the repository at this point in the history
transfer cache interceptor should not run again on the client as it is intended for server to client handoff

PR Close #55012
  • Loading branch information
Jefftopia authored and atscott committed Apr 9, 2024
1 parent 545fb0d commit 766548c
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
8 changes: 6 additions & 2 deletions packages/common/http/src/transfer_cache.ts
Expand Up @@ -19,6 +19,7 @@ import {
ɵperformanceMarkFeature as performanceMarkFeature,
ɵtruncateMiddle as truncateMiddle,
ɵwhenStable as whenStable,
PLATFORM_ID,
} from '@angular/core';
import {Observable, of} from 'rxjs';
import {tap} from 'rxjs/operators';
Expand All @@ -29,6 +30,7 @@ import {HTTP_ROOT_INTERCEPTOR_FNS, HttpHandlerFn} from './interceptor';
import {HttpRequest} from './request';
import {HttpEvent, HttpResponse} from './response';
import {HttpParams} from './params';
import {isPlatformServer} from '@angular/common';

/**
* Options to configure how TransferCache should be used to cache requests made via HttpClient.
Expand Down Expand Up @@ -160,10 +162,12 @@ export function transferCacheInterceptorFn(
);
}

// Request not found in cache. Make the request and cache it.
const isServer = isPlatformServer(inject(PLATFORM_ID));

// Request not found in cache. Make the request and cache it if on the server.
return next(req).pipe(
tap((event: HttpEvent<unknown>) => {
if (event instanceof HttpResponse) {
if (event instanceof HttpResponse && isServer) {
transferState.set<TransferHttpResponse>(storeKey, {
[BODY]: event.body,
[HEADERS]: getFilteredHeaders(event.headers, headersToInclude),
Expand Down
39 changes: 38 additions & 1 deletion packages/common/http/test/transfer_cache_spec.ts
Expand Up @@ -7,7 +7,7 @@
*/

import {DOCUMENT} from '@angular/common';
import {ApplicationRef, Component, Injectable} from '@angular/core';
import {ApplicationRef, Component, Injectable, PLATFORM_ID} from '@angular/core';
import {makeStateKey, TransferState} from '@angular/core/src/transfer_state';
import {fakeAsync, flush, TestBed} from '@angular/core/testing';
import {withBody} from '@angular/private/testing';
Expand Down Expand Up @@ -95,6 +95,7 @@ describe('TransferCache', () => {
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: PLATFORM_ID, useValue: 'server'},
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
withHttpTransferCache({}),
Expand Down Expand Up @@ -298,6 +299,41 @@ describe('TransferCache', () => {
});
});

describe('caching in browser context', () => {
beforeEach(
withBody('<test-app-http></test-app-http>', () => {
TestBed.resetTestingModule();
isStable = new BehaviorSubject<boolean>(false);

@Injectable()
class ApplicationRefPatched extends ApplicationRef {
override isStable = new BehaviorSubject<boolean>(false);
}

TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: PLATFORM_ID, useValue: 'browser'},
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
withHttpTransferCache({}),
provideHttpClient(),
provideHttpClientTesting(),
],
});

const appRef = TestBed.inject(ApplicationRef);
appRef.bootstrap(SomeComponent);
isStable = appRef.isStable as BehaviorSubject<boolean>;
}),
);

it('should skip storing in transfer cache when platform is browser', () => {
makeRequestAndExpectOne('/test-1?foo=1', 'foo');
makeRequestAndExpectOne('/test-1?foo=1', 'foo');
});
});

describe('caching with global setting', () => {
beforeEach(
withBody('<test-app-http></test-app-http>', () => {
Expand All @@ -312,6 +348,7 @@ describe('TransferCache', () => {
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: PLATFORM_ID, useValue: 'server'},
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
withHttpTransferCache({
Expand Down
Expand Up @@ -374,6 +374,9 @@
{
"name": "PLATFORM_INITIALIZER"
},
{
"name": "PLATFORM_SERVER_ID"
},
{
"name": "PRESERVE_HOST_CONTENT"
},
Expand Down
5 changes: 4 additions & 1 deletion packages/platform-browser/test/hydration_spec.ts
Expand Up @@ -9,7 +9,7 @@
import {DOCUMENT} from '@angular/common';
import {HttpClient, HttpTransferCacheOptions, provideHttpClient} from '@angular/common/http';
import {HttpTestingController, provideHttpClientTesting} from '@angular/common/http/testing';
import {ApplicationRef, Component, Injectable, ɵSSR_CONTENT_INTEGRITY_MARKER as SSR_CONTENT_INTEGRITY_MARKER} from '@angular/core';
import {ApplicationRef, Component, Injectable, PLATFORM_ID, ɵSSR_CONTENT_INTEGRITY_MARKER as SSR_CONTENT_INTEGRITY_MARKER} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {withBody} from '@angular/private/testing';
import {BehaviorSubject} from 'rxjs';
Expand Down Expand Up @@ -47,6 +47,7 @@ describe('provideClientHydration', () => {
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: PLATFORM_ID, useValue: 'server'},
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
provideClientHydration(),
Expand Down Expand Up @@ -74,6 +75,7 @@ describe('provideClientHydration', () => {
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: PLATFORM_ID, useValue: 'server'},
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
provideClientHydration(withNoHttpTransferCache()),
Expand Down Expand Up @@ -101,6 +103,7 @@ describe('provideClientHydration', () => {
TestBed.configureTestingModule({
declarations: [SomeComponent],
providers: [
{provide: PLATFORM_ID, useValue: 'server'},
{provide: DOCUMENT, useFactory: () => document},
{provide: ApplicationRef, useClass: ApplicationRefPatched},
provideClientHydration(withHttpTransferCacheOptions(
Expand Down

0 comments on commit 766548c

Please sign in to comment.