FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(http): skip transfer cache for fetch credentialed requests · angular/angular@8ec0197 · GitHub

Commit 8ec0197

Browse files
committed
fix(http): skip transfer cache for fetch credentialed requests
Treat HttpClient requests using `credentials: 'include'` and `same-origin` as credentialed when deciding whether a response can be stored in the HTTP transfer cache. The transfer cache already skips requests with `withCredentials`, `Cookie`, `Authorization`, or `Proxy-Authorization` because those responses may contain user-specific data. Fetch-backed requests can express the same credentialed behavior through the `credentials` option, so these responses must not be serialized into the SSR HTML. This keeps credentialed SSR responses out of TransferState and aligns the cache eligibility check with the fetch request options supported by HttpClient.
1 parent 45e8fb5 commit 8ec0197

3 files changed

Lines changed: 50 additions & 4 deletions

File tree

‎adev/src/content/guide/ssr.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ To configure this, update your `angular.json` file as follows:
432432
You can customize how Angular caches HTTP responses during server‑side rendering (SSR) and reuses them during hydration by configuring `HttpTransferCacheOptions`.
433433
This configuration is provided globally using `withHttpTransferCacheOptions` inside `provideClientHydration()`.
434434

435-
By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers and are not sent with `withCredentials`. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration.
435+
By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers and are not sent with `withCredentials` or Fetch API `credentials` modes that can send credentials. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration.
436436

437437
```ts
438438
import {bootstrapApplication} from '@angular/platform-browser';
@@ -487,7 +487,7 @@ Use this only when `POST` requests are **idempotent** and safe to reuse between
487487
### `includeRequestsWithAuthHeaders`
488488

489489
Determines whether requests containing `Authorization`, `Proxy‑Authorization`, or `Cookie` headers are eligible for caching.
490-
By default, these are excluded to prevent caching user‑specific responses. Requests sent with `withCredentials` are also excluded by default.
490+
By default, these are excluded to prevent caching user‑specific responses. Requests sent with `withCredentials` or Fetch API `credentials` set to `include` or `same-origin` are also excluded by default.
491491

492492
```ts
493493
withHttpTransferCacheOptions({

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ import {HttpParams} from './params';
4242
* (for example using GraphQL).
4343
* @param includeRequestsWithAuthHeaders Enables caching of requests containing `Authorization`,
4444
* `Proxy-Authorization`, or `Cookie` headers. By default, these requests are excluded from
45-
* caching. Requests sent using `withCredentials` are also excluded by default.
45+
* caching. Requests sent using `withCredentials` or Fetch API `credentials` modes that can send
46+
* credentials are also excluded by default.
4647
*
4748
* @see [Configuring the caching options](guide/ssr#configuring-the-caching-options)
4849
*
@@ -132,7 +133,7 @@ function shouldCacheRequest(req: HttpRequest<unknown>, options: CacheOptions): b
132133
!isCacheActive ||
133134
requestOptions === false ||
134135
// Do not cache requests sent with credentials.
135-
req.withCredentials ||
136+
hasOutgoingCredentials(req) ||
136137
// POST requests are allowed either globally or at request level
137138
(requestMethod === 'POST' && !globalOptions.includePostRequests && !requestOptions) ||
138139
(requestMethod !== 'POST' && !ALLOWED_METHODS.includes(requestMethod)) ||
@@ -300,6 +301,10 @@ function hasAuthHeaders(req: HttpRequest<unknown>): boolean {
300301
);
301302
}
302303

304+
function hasOutgoingCredentials(req: HttpRequest<unknown>): boolean {
305+
return req.withCredentials || req.credentials === 'include' || req.credentials === 'same-origin';
306+
}
307+
303308
function getFilteredHeaders(
304309
headers: HttpHeaders,
305310
includeHeaders: string[] | undefined,

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ interface RequestParams {
4141
transferCache?: {includeHeaders: string[]} | boolean;
4242
headers?: {[key: string]: string};
4343
withCredentials?: boolean;
44+
credentials?: RequestCredentials;
4445
body?: RequestBody;
4546
}
4647

@@ -440,6 +441,36 @@ describe('TransferCache', () => {
440441
});
441442
});
442443

444+
it('should not cache requests with included credentials', async () => {
445+
makeRequestAndExpectOne('/test-auth', 'foo', {
446+
credentials: 'include',
447+
});
448+
449+
makeRequestAndExpectOne('/test-auth', 'foo', {
450+
credentials: 'include',
451+
});
452+
});
453+
454+
it('should not cache requests with same-origin credentials', async () => {
455+
makeRequestAndExpectOne('/test-auth', 'foo', {
456+
credentials: 'same-origin',
457+
});
458+
459+
makeRequestAndExpectOne('/test-auth', 'foo', {
460+
credentials: 'same-origin',
461+
});
462+
});
463+
464+
it('should cache requests with omitted credentials', async () => {
465+
makeRequestAndExpectOne('/test-auth', 'foo', {
466+
credentials: 'omit',
467+
});
468+
469+
makeRequestAndExpectNone('/test-auth', 'GET', {
470+
credentials: 'omit',
471+
});
472+
});
473+
443474
it('should cache POST with the differing body in string form', () => {
444475
makeRequestAndExpectOne('/test-1', null, {method: 'POST', transferCache: true, body: 'foo'});
445476
makeRequestAndExpectNone('/test-1', 'POST', {transferCache: true, body: 'foo'});
@@ -602,6 +633,16 @@ describe('TransferCache', () => {
602633
});
603634
});
604635

636+
it(`should not cache requests with included credentials when 'includeRequestsWithAuthHeaders' is 'true'`, async () => {
637+
makeRequestAndExpectOne('/test-auth', 'foo', {
638+
credentials: 'include',
639+
});
640+
641+
makeRequestAndExpectOne('/test-auth', 'foo', {
642+
credentials: 'include',
643+
});
644+
});
645+
605646
it('should cache a POST request', () => {
606647
makeRequestAndExpectOne('/include?foo=1', 'post-body', {method: 'POST'});
607648

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL