-
Notifications
You must be signed in to change notification settings - Fork 27.4k
docs: Adds HTTP communication guidance to Angular Skills #69645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+116
−2
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
skills/dev-skills/angular-developer/references/http-client.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| # HTTP communication with `HttpClient` and `httpResource` | ||
|
|
||
| Use Angular's HTTP APIs for backend communication so requests participate in dependency injection, interceptors, transfer cache, and security features. | ||
|
|
||
| ## Setup | ||
|
|
||
| In Angular v21 and later, `HttpClient` is available for injection by default. Add `provideHttpClient(...)` only when an app needs to configure HTTP features for a specific injector: | ||
|
|
||
| ```ts | ||
| import {provideHttpClient, withInterceptors} from '@angular/common/http'; | ||
|
|
||
| export const appConfig = { | ||
| providers: [provideHttpClient(withInterceptors([authInterceptor]))], | ||
| }; | ||
| ``` | ||
|
|
||
| - `HttpClient` uses the fetch backend by default. | ||
| - Use `withXhr()` only when upload progress events are required. Do not use `withXhr()` for server-side rendering. | ||
| - Use `provideHttpClient(...)` for feature configuration such as interceptors, XSRF options, XHR, or parent-request delegation. | ||
| - Calling `provideHttpClient()` with no features is not required for basic HTTP requests, but it configures the default HTTP feature set for that injector, including Angular's XSRF interceptor. | ||
| - Prefer `provideHttpClient(...)` over `HttpClientModule` for feature configuration, especially with multiple injectors. | ||
| - Use `withRequestsMadeViaParent()` when a child injector should add interceptors while still delegating to the parent HTTP chain. | ||
|
|
||
| ## `HttpClient` | ||
|
|
||
| Encapsulate backend calls in injectable services, not components: | ||
|
|
||
| ```ts | ||
| import {HttpClient} from '@angular/common/http'; | ||
| import {Service, inject} from '@angular/core'; | ||
|
|
||
| @Service() | ||
| export class UserService { | ||
| private readonly http = inject(HttpClient); | ||
|
|
||
| getUser(id: string) { | ||
| return this.http.get<User>(`/api/users/${id}`); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Important rules: | ||
|
|
||
| - `HttpClient` requests are cold `Observable`s. No request is sent until the `Observable` is subscribed to. Multiple subscriptions send multiple backend requests. | ||
| - Subscribe to mutation requests (`post`, `put`, `patch`, `delete`) so they execute. | ||
| - The generic type parameter is a type assertion only. Validate unknown backend data at runtime when the shape is not trusted. | ||
| - Use literal values for `responseType` and `observe`; if options are extracted, write values like `responseType: 'text' as const`. | ||
| - `HttpHeaders` and `HttpParams` are immutable; use the returned instance from `.set()` or `.append()`. | ||
| - Fetch options such as `timeout`, `cache`, `priority`, `mode`, `redirect`, `credentials`, `keepalive`, `referrer`, `referrerPolicy`, and `integrity` are supported where the backend supports them. `withCredentials: true` overrides `credentials`. | ||
| - Handle failures through `HttpErrorResponse`. Network and timeout failures use status `0`; backend failures use the server status code. | ||
| - Prefer the `async` pipe or `toSignal` for component reads so subscriptions are cleaned up. | ||
|
|
||
| ## Interceptors | ||
|
|
||
| Prefer functional interceptors configured with `withInterceptors`. | ||
|
|
||
| ```ts | ||
| import { | ||
| HttpHandlerFn, | ||
| HttpRequest, | ||
| provideHttpClient, | ||
| withInterceptors, | ||
| } from '@angular/common/http'; | ||
|
|
||
| export function authInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn) { | ||
| return next(req.clone({setHeaders: {Authorization: 'Bearer token'}})); | ||
| } | ||
|
|
||
| export const appConfig = { | ||
| providers: [provideHttpClient(withInterceptors([authInterceptor]))], | ||
| }; | ||
| ``` | ||
|
|
||
| - Interceptors run in the order listed. | ||
| - Request and response objects are mostly immutable; clone before changing them. | ||
| - Request and response bodies are not deeply immutable. Avoid in-place body mutation because retries can run the same interceptor again. | ||
| - Use `inject()` inside functional interceptors for services. | ||
| - Use `HttpContextToken` for per-request metadata that interceptors need but the backend should not receive. | ||
| - Use DI-based interceptors only for existing code, and enable them with `withInterceptorsFromDi()`. | ||
|
|
||
| ## Security | ||
|
|
||
| - `HttpClient` strips the XSSI prefix from JSON responses when present. | ||
| - `provideHttpClient()` configures XSRF protection by default for mutating relative and same-origin requests. It reads the `XSRF-TOKEN` cookie and sends the `X-XSRF-TOKEN` header. | ||
| - The backend must set the XSRF cookie and verify the header. Customize names with `withXsrfConfiguration(...)`; disable only deliberately with `withNoXsrfProtection()`. | ||
|
|
||
| ## `httpResource` | ||
|
|
||
| Use `httpResource` to create an asynchronous derivation that fetches data over HTTP and exposes the result as reactive signals. | ||
|
|
||
| ```ts | ||
| import {httpResource} from '@angular/common/http'; | ||
| import {input} from '@angular/core'; | ||
|
|
||
| export class UserProfile { | ||
| readonly userId = input.required<string>(); | ||
| readonly user = httpResource(() => `/api/users/${this.userId()}`); | ||
| } | ||
| ``` | ||
|
|
||
| - `httpResource` is eager. It sends a request when its reactive request computation runs, not when an `Observable` is subscribed. | ||
| - When a dependency changes, it cancels the pending request and sends the next one. | ||
| - Return `undefined` from the request function to skip a backend request. | ||
| - Prefer `httpResource` for reads. Use `HttpClient` directly for mutations such as `POST`, `PUT`, `PATCH`, and `DELETE`. | ||
| - Guard `value()` reads with `hasValue()`; reading `value()` while the resource is in an error state throws. | ||
| - Use `httpResource.text`, `httpResource.blob`, or `httpResource.arrayBuffer` for non-JSON responses. | ||
| - Use the `parse` option to validate or transform responses with a runtime schema. | ||
| - Read `headers()`, `statusCode()`, and `progress()` when response metadata or download progress is needed. Set `reportProgress: true` for progress events. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.