@@ -114,7 +114,7 @@ interface CacheOptions extends HttpTransferCacheOptions {
114114 isCacheActive : boolean ;
115115}
116116
117- const CACHE_OPTIONS = new InjectionToken < CacheOptions > (
117+ export const CACHE_OPTIONS = new InjectionToken < CacheOptions > (
118118 typeof ngDevMode !== 'undefined' && ngDevMode ? 'HTTP_TRANSFER_STATE_CACHE_OPTIONS' : '' ,
119119) ;
120120
@@ -123,14 +123,10 @@ const CACHE_OPTIONS = new InjectionToken<CacheOptions>(
123123 */
124124const ALLOWED_METHODS = [ 'GET' , 'HEAD' ] ;
125125
126- export function transferCacheInterceptorFn (
127- req : HttpRequest < unknown > ,
128- next : HttpHandlerFn ,
129- ) : Observable < HttpEvent < unknown > > {
130- const { isCacheActive, ...globalOptions } = inject ( CACHE_OPTIONS ) ;
126+ function shouldCacheRequest ( req : HttpRequest < unknown > , options : CacheOptions ) : boolean {
127+ const { isCacheActive, ...globalOptions } = options ;
131128 const { transferCache : requestOptions , method : requestMethod } = req ;
132129
133- // In the following situations we do not want to cache the request
134130 if (
135131 ! isCacheActive ||
136132 requestOptions === false ||
@@ -141,14 +137,37 @@ export function transferCacheInterceptorFn(
141137 ( ! globalOptions . includeRequestsWithAuthHeaders && hasAuthHeaders ( req ) ) ||
142138 globalOptions . filter ?.( req ) === false
143139 ) {
144- return next ( req ) ;
140+ return false ;
145141 }
146142
147- const transferState = inject ( TransferState ) ;
143+ return true ;
144+ }
148145
149- const originMap : Record < string , string > | null = inject ( HTTP_TRANSFER_CACHE_ORIGIN_MAP , {
150- optional : true ,
151- } ) ;
146+ function getHeadersToInclude (
147+ options : CacheOptions ,
148+ requestOptions : HttpTransferCacheOptions | boolean | undefined ,
149+ ) : string [ ] | undefined {
150+ const { includeHeaders : globalHeaders } = options ;
151+ let headersToInclude = globalHeaders ;
152+ if ( typeof requestOptions === 'object' && requestOptions . includeHeaders ) {
153+ // Request-specific config takes precedence over the global config.
154+ headersToInclude = requestOptions . includeHeaders ;
155+ }
156+ return headersToInclude ;
157+ }
158+
159+ export function retrieveStateFromCache (
160+ req : HttpRequest < unknown > ,
161+ options : CacheOptions ,
162+ transferState : TransferState ,
163+ originMap : Record < string , string > | null ,
164+ ) : HttpResponse < unknown > | null {
165+ const { transferCache : requestOptions } = req ;
166+
167+ // In the following situations we do not want to cache the request
168+ if ( ! shouldCacheRequest ( req , options ) ) {
169+ return null ;
170+ }
152171
153172 if ( typeof ngServerMode !== 'undefined' && ! ngServerMode && originMap ) {
154173 throw new RuntimeError (
@@ -168,11 +187,7 @@ export function transferCacheInterceptorFn(
168187 const storeKey = makeCacheKey ( req , requestUrl ) ;
169188 const response = transferState . get ( storeKey , null ) ;
170189
171- let headersToInclude = globalOptions . includeHeaders ;
172- if ( typeof requestOptions === 'object' && requestOptions . includeHeaders ) {
173- // Request-specific config takes precedence over the global config.
174- headersToInclude = requestOptions . includeHeaders ;
175- }
190+ const headersToInclude = getHeadersToInclude ( options , requestOptions ) ;
176191
177192 if ( response ) {
178193 const {
@@ -206,15 +221,44 @@ export function transferCacheInterceptorFn(
206221 headers = appendMissingHeadersDetection ( req . url , headers , headersToInclude ?? [ ] ) ;
207222 }
208223
209- return of (
210- new HttpResponse ( {
211- body,
212- headers,
213- status,
214- statusText,
215- url,
216- } ) ,
217- ) ;
224+ return new HttpResponse ( {
225+ body,
226+ headers,
227+ status,
228+ statusText,
229+ url,
230+ } ) ;
231+ }
232+
233+ return null ;
234+ }
235+
236+ export function transferCacheInterceptorFn (
237+ req : HttpRequest < unknown > ,
238+ next : HttpHandlerFn ,
239+ ) : Observable < HttpEvent < unknown > > {
240+ const options = inject ( CACHE_OPTIONS ) ;
241+ const transferState = inject ( TransferState ) ;
242+
243+ const originMap = inject ( HTTP_TRANSFER_CACHE_ORIGIN_MAP , { optional : true } ) ;
244+
245+ const cachedResponse = retrieveStateFromCache ( req , options , transferState , originMap ) ;
246+ if ( cachedResponse ) {
247+ return of ( cachedResponse ) ;
248+ }
249+
250+ const { transferCache : requestOptions } = req ;
251+ const headersToInclude = getHeadersToInclude ( options , requestOptions ) ;
252+
253+ const requestUrl =
254+ typeof ngServerMode !== 'undefined' && ngServerMode && originMap
255+ ? mapRequestOriginUrl ( req . url , originMap )
256+ : req . url ;
257+ const storeKey = makeCacheKey ( req , requestUrl ) ;
258+
259+ // In the following situations we do not want to cache the request
260+ if ( ! shouldCacheRequest ( req , options ) ) {
261+ return next ( req ) ;
218262 }
219263
220264 const event$ = next ( req ) ;
0 commit comments