From 09abee359dcde4922684627fbb4bc52fe6ee462d Mon Sep 17 00:00:00 2001 From: Kapunahele Wong Date: Fri, 16 Apr 2021 16:02:42 -0400 Subject: [PATCH] docs: add metadata documentation to httpClient (#41706) PR Close #41706 --- .../http-interceptors/retry-interceptor.ts | 50 +++++++++++++++++++ aio/content/guide/http.md | 49 +++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 aio/content/examples/http/src/app/http-interceptors/retry-interceptor.ts diff --git a/aio/content/examples/http/src/app/http-interceptors/retry-interceptor.ts b/aio/content/examples/http/src/app/http-interceptors/retry-interceptor.ts new file mode 100644 index 0000000000000..2eb562625df56 --- /dev/null +++ b/aio/content/examples/http/src/app/http-interceptors/retry-interceptor.ts @@ -0,0 +1,50 @@ +// #docplaster +import {HttpClient, HttpContext, HttpContextToken, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http'; +import {Observable} from 'rxjs'; +/* +// #docregion reading-context +import {retry} from 'rxjs'; +// #enddocregion reading-context +*/ +// #docregion mutable-context +import {retry, tap} from 'rxjs/operators'; +// #enddocregion mutable-context + +// #docregion context-token, mutable-context +export const RETRY_COUNT = new HttpContextToken(() => 3); +// #enddocregion context-token +export const ERROR_COUNT = new HttpContextToken(() => 0); +// #enddocregion mutable-context + +export class FakeService { + constructor(private httpClient: HttpClient) { + // #docregion set-context + this.httpClient + .get('/data/feed', { + context: new HttpContext().set(RETRY_COUNT, 5), + }) + .subscribe(results => {/* ... */}); + // #enddocregion set-context + } +} + +// #docregion reading-context, mutable-context + +export class RetryInterceptor implements HttpInterceptor { + intercept(req: HttpRequest, next: HttpHandler): Observable> { + const retryCount = req.context.get(RETRY_COUNT); + + return next.handle(req).pipe( + // #enddocregion reading-context + tap(null, + () => { + // An error has occurred, so increment this request's ERROR_COUNT. + req.set(ERROR_COUNT, req.get(ERROR_COUNT) + 1); + }), + // #docregion reading-context + // Retry the request a configurable number of times. + retry(retryCount), + ); + } +} +// #enddocregion reading-context, mutable-context diff --git a/aio/content/guide/http.md b/aio/content/guide/http.md index 188792245ee1c..70bd85f10f1e5 100644 --- a/aio/content/guide/http.md +++ b/aio/content/guide/http.md @@ -812,7 +812,7 @@ Neither `tap` nor `finalize` touch the values of the observable stream returned Interceptors can be used to replace the built-in JSON parsing with a custom implementation. The `CustomJsonInterceptor` in the following example demonstrates how to achieve this. -If the intercepted request expects a `'json'` response, the `reponseType` is changed to `'text'` +If the intercepted request expects a `'json'` response, the `responseType` is changed to `'text'` to disable the built-in JSON parsing. Then the response is parsed via the injected `JsonParser`. + + +## Passing metadata to interceptors + +Many interceptors require or benefit from configuration. Consider an interceptor that retries failed requests. +By default, the interceptor might retry a request three times, but you might want to override this retry count for particularly error-prone or sensitive requests. + +`HttpClient` requests contain a _context_ that can carry metadata about the request. +This context is available for interceptors to read or modify, though it is not transmitted to the backend server when the request is sent. +This allows applications or other interceptors to tag requests with configuration parameters, such as how many times to retry a request. + +### Creating a context token + +Angular stores and retrieves a value in the context using an `HttpContextToken`. +You can create a context token using the `new` operator, as in the following example: + + + +The lambda function `() => 3` passed during the creation of the `HttpContextToken` serves two purposes: + +1. It allows TypeScript to infer the type of this token: `HttpContextToken`. + The request context is type-safe—reading a token from a request's context returns a value of the appropriate type. + +1. It sets the default value for the token. + This is the value that the request context returns if no other value has been set for this token. + Using a default value avoids the need to check if a particular value is set. + +### Setting context values when making a request + +When making a request, you can provide an `HttpContext` instance, in which you have already set the context values. + + + +### Reading context values in an interceptor + +Within an interceptor, you can read the value of a token in a given request's context with `HttpContext.get()`. +If you have not explicitly set a value for the token, Angular returns the default value specified in the token. + + + +### Contexts are mutable + +Unlike most other aspects of `HttpRequest` instances, the request context is mutable and persists across other immutable transformations of the request. +This allows interceptors to coordinate operations through the context. +For instance, the `RetryInterceptor` example could use a second context token to track how many errors occur during the execution of a given request: + +