`.
Many interceptors are only concerned with the outgoing request and return the event stream from `next.handle()` without modifying it.
Some interceptors, however, need to examine and modify the response from `next.handle()`; these operations can see all of these events in the stream.
{@a immutability}
Although interceptors are capable of modifying requests and responses,
the `HttpRequest` and `HttpResponse` instance properties are `readonly`,
rendering them largely immutable.
They are immutable for a good reason: an app might retry a request several times before it succeeds, which means that the interceptor chain can re-process the same request multiple times.
If an interceptor could modify the original request object, the re-tried operation would start from the modified request rather than the original. Immutability ensures that interceptors see the same request for each try.
Your interceptor should return every event without modification unless it has a compelling reason to do otherwise.
TypeScript prevents you from setting `HttpRequest` read-only properties.
```javascript
// Typescript disallows the following assignment because req.url is readonly
req.url = req.url.replace('http://', 'https://');
```
If you must alter a request, clone it first and modify the clone before passing it to `next.handle()`.
You can clone and modify the request in a single step, as shown in the following example.
The `clone()` method's hash argument allows you to mutate specific properties of the request while copying the others.
#### Modifying a request body
The `readonly` assignment guard can't prevent deep updates and, in particular,
it can't prevent you from modifying a property of a request body object.
```javascript
req.body.name = req.body.name.trim(); // bad idea!
```
If you must modify the request body, follow these steps.
1. Copy the body and make your change in the copy.
2. Clone the request object, using its `clone()` method.
3. Replace the clone's body with the modified copy.
#### Clearing the request body in a clone
Sometimes you need to clear the request body rather than replace it.
To do this, set the cloned request body to `null`.
**Tip**: If you set the cloned request body to `undefined`, Angular assumes you intend to leave the body as is.
```javascript
newReq = req.clone({ ... }); // body not mentioned => preserve original body
newReq = req.clone({ body: undefined }); // preserve original body
newReq = req.clone({ body: null }); // clear the body
```
## Http interceptor use-cases
Below are a number of common uses for interceptors.
### Setting default headers
Apps often use an interceptor to set default headers on outgoing requests.
The sample app has an `AuthService` that produces an authorization token.
Here is its `AuthInterceptor` that injects that service to get the token and
adds an authorization header with that token to every outgoing request:
The practice of cloning a request to set new headers is so common that
there's a `setHeaders` shortcut for it:
An interceptor that alters headers can be used for a number of different operations, including:
* Authentication/authorization
* Caching behavior; for example, `If-Modified-Since`
* XSRF protection
### Logging request and response pairs
Because interceptors can process the request and response _together_, they can perform tasks such as timing and logging an entire HTTP operation.
Consider the following `LoggingInterceptor`, which captures the time of the request,
the time of the response, and logs the outcome with the elapsed time
with the injected `MessageService`.
The RxJS `tap` operator captures whether the request succeeded or failed.
The RxJS `finalize` operator is called when the response observable either errors or completes (which it must),
and reports the outcome to the `MessageService`.
Neither `tap` nor `finalize` touch the values of the observable stream returned to the caller.
{@a custom-json-parser}
### Custom JSON parsing
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 `responseType` is changed to `'text'`
to disable the built-in JSON parsing. Then the response is parsed via the injected `JsonParser`.
You can then implement your own custom `JsonParser`.
Here is a custom JsonParser that has a special date reviver.
You provide the `CustomParser` along with the `CustomJsonInterceptor`.
{@a caching}
### Caching requests
Interceptors can handle requests by themselves, without forwarding to `next.handle()`.
For example, you might decide to cache certain requests and responses to improve performance.
You can delegate caching to an interceptor without disturbing your existing data services.
The `CachingInterceptor` in the following example demonstrates this approach.
* The `isCacheable()` function determines if the request is cacheable.
In this sample, only GET requests to the npm package search api are cacheable.
* If the request is not cacheable, the interceptor forwards the request
to the next handler in the chain.
* If a cacheable request is found in the cache, the interceptor returns an `of()` _observable_ with
the cached response, by-passing the `next` handler (and all other interceptors downstream).
* If a cacheable request is not in cache, the code calls `sendRequest()`.
This function creates a [request clone](#immutability) without headers, because the npm API forbids them.
The function then forwards the clone of the request to `next.handle()` which ultimately calls the server and returns the server's response.
{@a send-request}
Note how `sendRequest()` intercepts the response on its way back to the application.
This method pipes the response through the `tap()` operator, whose callback adds the response to the cache.
The original response continues untouched back up through the chain of interceptors
to the application caller.
Data services, such as `PackageSearchService`, are unaware that
some of their `HttpClient` requests actually return cached responses.
{@a cache-refresh}
### Using interceptors to request multiple values
The `HttpClient.get()` method normally returns an observable that emits a single value, either the data or an error.
An interceptor can change this to an observable that emits [multiple values](guide/observables).
The following revised version of the `CachingInterceptor` optionally returns an observable that
immediately emits the cached response, sends the request on to the npm web API,
and emits again later with the updated search results.
The _cache-then-refresh_ option is triggered by the presence of a custom `x-refresh` header.
A checkbox on the `PackageSearchComponent` toggles a `withRefresh` flag,
which is one of the arguments to `PackageSearchService.search()`.
That `search()` method creates the custom `x-refresh` header
and adds it to the request before calling `HttpClient.get()`.
The revised `CachingInterceptor` sets up a server request
whether there's a cached value or not,
using the same `sendRequest()` method described [above](#send-request).
The `results$` observable makes the request when subscribed.
* If there's no cached value, the interceptor returns `results$`.
* If there is a cached value, the code _pipes_ the cached response onto
`results$`, producing a recomposed observable that emits twice,
the cached response first (and immediately), followed later
by the response from the server.
Subscribers see a sequence of two responses.
{@a report-progress}
## Tracking and showing request progress
Sometimes applications transfer large amounts of data and those transfers can take a long time.
File uploads are a typical example.
You can give the users a better experience by providing feedback on the progress of such transfers.
To make a request with progress events enabled, you can create an instance of `HttpRequest`
with the `reportProgress` option set true to enable tracking of progress events.
**Tip**: Every progress event triggers change detection, so only turn them on if you need to report progress in the UI.
When using [`HttpClient.request()`](api/common/http/HttpClient#request) with an HTTP method, configure the method with
[`observe: 'events'`](api/common/http/HttpClient#request) to see all events, including the progress of transfers.
Next, pass this request object to the `HttpClient.request()` method, which
returns an `Observable` of `HttpEvents` (the same events processed by [interceptors](#interceptor-events)).
The `getEventMessage` method interprets each type of `HttpEvent` in the event stream.
The sample app for this guide doesn't have a server that accepts uploaded files.
The `UploadInterceptor` in `app/http-interceptors/upload-interceptor.ts`
intercepts and short-circuits upload requests
by returning an observable of simulated events.
## Optimizing server interaction with debouncing
If you need to make an HTTP request in response to user input, it's not efficient to send a request for every keystroke.
It's better to wait until the user stops typing and then send a request.
This technique is known as debouncing.
Consider the following template, which lets a user enter a search term to find an npm package by name.
When the user enters a name in a search-box, the `PackageSearchComponent` sends
a search request for a package with that name to the npm web API.
Here, the `keyup` event binding sends every keystroke to the component's `search()` method.
The type of `$event.target` is only `EventTarget` in the template.
In the `getValue()` method, the target is cast to an `HTMLInputElement` to allow type-safe access to its `value` property.
The following snippet implements debouncing for this input using RxJS operators.
The `searchText$` is the sequence of search-box values coming from the user.
It's defined as an RxJS `Subject`, which means it is a multicasting `Observable`
that can also emit values for itself by calling `next(value)`,
as happens in the `search()` method.
Rather than forward every `searchText` value directly to the injected `PackageSearchService`,
the code in `ngOnInit()` pipes search values through three operators, so that a search value reaches the service only if it's a new value and the user has stopped typing.
* `debounceTime(500)`—Wait for the user to stop typing (1/2 second in this case).
* `distinctUntilChanged()`—Wait until the search text changes.
* `switchMap()`—Send the search request to the service.
The code sets `packages$` to this re-composed `Observable` of search results.
The template subscribes to `packages$` with the [AsyncPipe](api/common/AsyncPipe)
and displays search results as they arrive.
See [Using interceptors to request multiple values](#cache-refresh) for more about the `withRefresh` option.
### Using the *switchMap()* operator
The `switchMap()` operator takes a function argument that returns an `Observable`.
In the example, `PackageSearchService.search` returns an `Observable`, as other data service methods do.
If a previous search request is still in-flight (as when the network connection is poor),
the operator cancels that request and sends a new one.
Note that `switchMap()` returns service responses in their original request order, even if the
server returns them out of order.
If you think you'll reuse this debouncing logic,
consider moving it to a utility function or into the `PackageSearchService` itself.
## Security: XSRF protection
[Cross-Site Request Forgery (XSRF or CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by which the attacker can trick an authenticated user into unknowingly executing actions on your website.
`HttpClient` supports a [common mechanism](https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token) used to prevent XSRF attacks.
When performing HTTP requests, an interceptor reads a token from a cookie, by default `XSRF-TOKEN`, and sets it as an HTTP header, `X-XSRF-TOKEN`.
Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
By default, an interceptor sends this header on all mutating requests (such as POST)
to relative URLs, but not on GET/HEAD requests or on requests with an absolute URL.
To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called `XSRF-TOKEN` on either the page load or the first GET request.
On subsequent requests the server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be sure that only code running on your domain could have sent the request.
The token must be unique for each user and must be verifiable by the server; this prevents the client from making up its own tokens.
Set the token to a digest of your site's authentication cookie with a salt for added security.
In order to prevent collisions in environments where multiple Angular apps share the same domain or subdomain, give each application a unique cookie name.
*`HttpClient` supports only the client half of the XSRF protection scheme.*
Your backend service must be configured to set the cookie for your page, and to verify that
the header is present on all eligible requests.
Failing to do so renders Angular's default protection ineffective.
### Configuring custom cookie/header names
If your backend service uses different names for the XSRF token cookie or header,
use `HttpClientXsrfModule.withOptions()` to override the defaults.
{@a testing-requests}
## Testing HTTP requests
As for any external dependency, you must mock the HTTP backend so your tests can simulate interaction with a remote server.
The `@angular/common/http/testing` library makes it straightforward to set up such mocking.
Angular's HTTP testing library is designed for a pattern of testing in which the app executes code and makes requests first.
The test then expects that certain requests have or have not been made,
performs assertions against those requests,
and finally provides responses by "flushing" each expected request.
At the end, tests can verify that the app has made no unexpected requests.
You can run these sample tests
in a live coding environment.
The tests described in this guide are in `src/testing/http-client.spec.ts`.
There are also tests of an application data service that call `HttpClient` in
`src/app/heroes/heroes.service.spec.ts`.
### Setup for testing
To begin testing calls to `HttpClient`,
import the `HttpClientTestingModule` and the mocking controller, `HttpTestingController`,
along with the other symbols your tests require.
Then add the `HttpClientTestingModule` to the `TestBed` and continue with
the setup of the _service-under-test_.
Now requests made in the course of your tests hit the testing backend instead of the normal backend.
This setup also calls `TestBed.inject()` to inject the `HttpClient` service and the mocking controller
so they can be referenced during the tests.
### Expecting and answering requests
Now you can write a test that expects a GET Request to occur and provides a mock response.
The last step, verifying that no requests remain outstanding, is common enough for you to move it into an `afterEach()` step:
#### Custom request expectations
If matching by URL isn't sufficient, it's possible to implement your own matching function.
For example, you could look for an outgoing request that has an authorization header:
As with the previous `expectOne()`,
the test fails if 0 or 2+ requests satisfy this predicate.
#### Handling more than one request
If you need to respond to duplicate requests in your test, use the `match()` API instead of `expectOne()`.
It takes the same arguments but returns an array of matching requests.
Once returned, these requests are removed from future matching and
you are responsible for flushing and verifying them.
### Testing for errors
You should test the app's defenses against HTTP requests that fail.
Call `request.flush()` with an error message, as seen in the following example.
Alternatively, you can call `request.error()` with an `ErrorEvent`.
## 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: