HTTP Interceptor не завершается (то есть finalize никогда не вызывается) - PullRequest
4 голосов
/ 21 января 2020

В моем проекте angular 8 я реализовал простейший из возможных HttpInterceptor, который просто передает запрос без каких-либо действий :

В моем проекте angular 8 я реализовал простой HttpInterceptor, который просто клонирует исходный запрос и добавляет параметр:

@Injectable()
export class RequestHeadersInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // original code return next.handle(request) // pass-by request as-is

    return next.handle(request.clone({
      params: request.params.set('language', 'en') }
    ));
  }
}

В моем сервисе у меня тогда есть метод getFoos(), который выполняет HTTP-вызов, который будет перехвачен RequestHeadersInterceptor:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { finalize } from 'rxjs/operators';
import { Foo } from '.';

@Injectable({
  providedIn: 'root'
})
export class FooService {
  constructor(private http: HttpClient) { }

  getFoos() {
    return this.http.get<Foo[]>('/foos')
      .pipe(
        finalize(() => console.log('observable completed!'))
      );
  }
}

В моем компоненте я наконец-то подписался на getFoos():

fooService.getFoos().subscribe(console.log);

Ожидаемый результат

[{ foo: 1 }, { foo: 2 }]
observable completed!

Фактический результат

[{ foo: 1 }, { foo: 2 }]

Как видите, finalize никогда не срабатывает. Почему это так?

Примечания

  • Если перехватчик удален, срабатывает finalize, что является ожидаемым поведением для обоих сценариев ios
  • Как я предоставляю перехватчик модулю:
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { RequestHeadersInterceptor } from './shared/http-requests';

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: RequestHeadersInterceptor, multi: true },
  ]
);
  • Я обновил код перехватчика, так как я ошибочно заявил, что проблема сохраняется даже при передаче по запросу как есть. Вместо этого его необходимо клонировать и изменить.

  • Я добавил демоверсию, основанную на демоверсии @ PierreDu c (основные реквизиты!). Однако я не смог воспроизвести проблему в демоверсии . Это может быть связано с некоторыми заголовками запросов или ответов.

Заголовки ответов в действующем системном API

Cache-Control: no-store, no-cache, must-revalidate, max-age=0 Cache-Control: post-check=0, pre-check=0
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Connection: keep-alive
Content-Language: en-US
Content-Length: 42
Content-Type: application/json;charset=utf-8
Date: Tue, 21 Jan 2020 15:44:33 GMT
Pragma: no-cache
Pragma: no-cache
Server: nginx/1.16.1
X-Content-Type-Options: nosniff
X-Powered-By: Servlet/3.1

Заголовки запросов в действующей системе API

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Authorization: Basic xyzABC123
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json
Cookie: check=true; anotherCookie=1; bla=2;
Host: some.page.com:11001
Pragma: no-cache
Referer: https://some.page.com
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36

1 Ответ

3 голосов
/ 22 января 2020

"Проблема" - заголовок Connection: Keep-Alive. При этом сохраняется открытое соединение

Общий заголовок соединения определяет, остается ли сетевое соединение открытым после завершения текущей транзакции. Если отправленное значение является keep-alive, соединение является постоянным и не закрывается, что позволяет выполнять последующие запросы к тому же серверу.

Это приведет к не завершению Observable до тех пор, пока соединение не будет установлено. прекращено.

Так что на самом деле это не ошибка или проблема на вашей стороне. Я полагаю, что в вашем HttpInterceptor вы добавляете этот заголовок, поэтому он вызывается только после добавления перехватчика

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...