@@ -393,6 +418,7 @@ Merely calling `HeroService.deleteHero()` **does not initiate the DELETE request
+
{@a always-subscribe}
@@ -432,6 +458,7 @@ req.subscribe();
req.subscribe();
// 2 requests made.
```
+
### Making a PUT request
@@ -443,6 +470,7 @@ The following `HeroService` example is just like the POST example.
path="http/src/app/heroes/heroes.service.ts"
region="updateHero"
title="app/heroes/heroes.service.ts (updateHero)" linenums="false">
+
For the reasons [explained above](#always-subscribe), the caller (`HeroesComponent.update()` in this case) must `subscribe()` to the observable returned from the `HttpClient.put()`
@@ -475,6 +503,7 @@ before making the next request.
@@ -586,6 +619,7 @@ To implement an interceptor, declare a class that implements the `intercept()` m
path="http/src/app/http-interceptors/noop-interceptor.ts"
title="app/http-interceptors/noop-interceptor.ts"
linenums="false">
+
The `intercept` method transforms a request into an `Observable` that eventually returns the HTTP response.
@@ -608,7 +642,6 @@ This _no-op_ interceptor simply calls `next.handle()` with the original request
The `next` object represents the next interceptor in the chain of interceptors.
The final `next` in the chain is the `HttpClient` backend handler that sends the request to the server and receives the server's response.
-
Most interceptors call `next.handle()` so that the request flows through to the next interceptor and, eventually, the backend handler.
An interceptor _could_ skip calling `next.handle()`, short-circuit the chain, and [return its own `Observable`](#caching) with an artificial server response.
@@ -632,6 +665,7 @@ write the `NoopInterceptor` provider like this:
+
Note the `multi: true` option.
@@ -650,6 +684,7 @@ Consider creating a "barrel" file that gathers all the interceptor providers int
path="http/src/app/http-interceptors/index.ts"
region="interceptor-providers"
title="app/http-interceptors/index.ts" linenums="false">
+
Then import and add it to the `AppModule` _providers array_ like this:
@@ -658,6 +693,7 @@ Then import and add it to the `AppModule` _providers array_ like this:
path="http/src/app/app.module.ts"
region="interceptor-providers"
title="app/app.module.ts (interceptor providers)" linenums="false">
+
As you create new interceptors, add them to the `httpInterceptorProviders` array and
@@ -714,6 +750,7 @@ You can clone and modify the request in a single step as in this example.
path="http/src/app/http-interceptors/ensure-https-interceptor.ts"
region="excerpt"
title="app/http-interceptors/ensure-https-interceptor.ts (excerpt)" linenums="false">
+
The `clone()` method's hash argument allows you to mutate specific properties of the request while copying the others.
@@ -734,6 +771,7 @@ If you must mutate the request body, copy it first, change the copy,
path="http/src/app/http-interceptors/trim-name-interceptor.ts"
region="excerpt"
title="app/http-interceptors/trim-name-interceptor.ts (excerpt)" linenums="false">
+
##### Clearing the request body
@@ -762,6 +800,7 @@ 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
@@ -770,6 +809,7 @@ there's a `setHeaders` shortcut for it:
+
An interceptor that alters headers can be used for a number of different operations, including:
@@ -778,15 +818,15 @@ An interceptor that alters headers can be used for a number of different operati
* Authentication/authorization
- 认证 / 授权
+ 认证 / 授权
* Caching behavior; for example, `If-Modified-Since`
- 控制缓存行为。比如`If-Modified-Since`
-
+ 控制缓存行为。比如`If-Modified-Since`
+
* XSRF protection
- XSRF 防护
+ XSRF 防护
#### Logging
@@ -803,6 +843,7 @@ with the injected `MessageService`.
path="http/src/app/http-interceptors/logging-interceptor.ts"
region="excerpt"
title="app/http-interceptors/logging-interceptor.ts)">
+
The RxJS `tap` operator captures whether the request succeed or failed.
@@ -826,6 +867,7 @@ The `CachingInterceptor` demonstrates this approach.
path="http/src/app/http-interceptors/caching-interceptor.ts"
region="v1"
title="app/http-interceptors/caching-interceptor.ts)" linenums="false">
+
The `isCachable()` function determines if the request is cachable.
@@ -843,6 +885,7 @@ If a cachable request is not in cache, the code calls `sendRequest`.
+
The `sendRequest` function creates a [request clone](#immutability) without headers
@@ -877,6 +920,7 @@ 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**.
@@ -920,6 +964,7 @@ with the `reportProgress` option set true to enable tracking of progress events.
path="http/src/app/uploader/uploader.service.ts"
region="upload-request"
title="app/uploader/uploader.service.ts (upload request)">
+
@@ -935,6 +980,7 @@ returns an `Observable` of `HttpEvents`, the same events processed by intercepto
path="http/src/app/uploader/uploader.service.ts"
region="upload-body"
title="app/uploader/uploader.service.ts (upload body)" linenums="false">
+
The `getEventMessage` method interprets each type of `HttpEvent` in the event stream.
@@ -943,6 +989,7 @@ The `getEventMessage` method interprets each type of `HttpEvent` in the event st
path="http/src/app/uploader/uploader.service.ts"
region="getEventMessage"
title="app/uploader/uploader.service.ts (getEventMessage)" linenums="false">
+
@@ -979,9 +1026,14 @@ In order to prevent collisions in environments where multiple Angular apps share
为了防止多个 Angular 应用共享同一个域名或子域时出现冲突,要给每个应用分配一个唯一的 cookie 名称。
-*Note that `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. If not, Angular's default protection will be ineffective.
+
+*Note that `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.
+If not, Angular's default protection will be ineffective.
*注意,`HttpClient`支持的只是 XSRF 防护方案的客户端这一半。* 我们的后端服务必须配置为给页面设置 cookie ,并且要验证请求头,以确保全都是合法的请求。否则,Angular 默认的这种防护措施就会失效。
+
### Configuring custom cookie/header names
@@ -997,6 +1049,7 @@ use `HttpClientXsrfModule.withOptions()` to override the defaults.
path="http/src/app/app.module.ts"
region="xsrf"
linenums="false">
+
## Testing HTTP requests
@@ -1020,12 +1073,15 @@ the the app executes code and makes requests first.
Then a test expects that certain requests have or have not been made,
performs assertions against those requests,
and finally provide responses by "flushing" each expected request.
-
+
At the end, tests may verify that the app has made no unexpected requests.
-You can run these sample tests
+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`.
@@ -1034,8 +1090,6 @@ There are also tests of an application data service that call `HttpClient` in
-Angular 的 HTTP 测试库是为这种模式的测试而设计的:应用执行代码并首先发起请求,之后,测试代码会期待(expect)特定的请求发起过或没发起,然后对那些请求进行断言,最终,通过刷新(flushing)每个被期待的请求来提供响应,此后还可能会触发更多新的请求。最后,测试代码还可以根据需要去验证应用不曾发起过预期之外的请求。
-
### Setup
### 初始设置
@@ -1050,6 +1104,7 @@ along with the other symbols your tests require.
path="http/src/testing/http-client.spec.ts"
region="imports"
title="app/testing/http-client.spec.ts (imports)" linenums="false">
+
Then add the `HttpClientTestingModule` to the `TestBed` and continue with
@@ -1059,6 +1114,7 @@ the setup of the _service-under-test_.
path="http/src/testing/http-client.spec.ts"
region="setup"
title="app/testing/http-client.spec.ts(setup)" linenums="false">
+
Now requests made in the course of your tests will hit the testing backend instead of the normal backend.
@@ -1076,6 +1132,7 @@ Now you can write a test that expects a GET Request to occur and provides a mock
path="http/src/testing/http-client.spec.ts"
region="get-test"
title="app/testing/http-client.spec.ts(httpClient.get)" linenums="false">
+
The last step, verifying that no requests remain outstanding, is common enough for you to move it into an `afterEach()` step:
@@ -1084,6 +1141,7 @@ The last step, verifying that no requests remain outstanding, is common enough f
path="http/src/testing/http-client.spec.ts"
region="afterEach"
linenums="false">
+
#### Custom request expectations
@@ -1097,6 +1155,7 @@ For example, you could look for an outgoing request that has an authorization he
path="http/src/testing/http-client.spec.ts"
region="predicate"
linenums="false">
+
As with the previous `expectOne()`,
@@ -1119,6 +1178,7 @@ you are responsible for flushing and verifying them.
path="http/src/testing/http-client.spec.ts"
region="multi-request"
linenums="false">
+
### Testing for errors
@@ -1131,4 +1191,6 @@ Call `request.error()` with an `ErrorEvent` instead of `request.flush()`, as in
path="http/src/testing/http-client.spec.ts"
region="404"
linenums="false">
+
+