Angular 4 - HTTP-перехватчик

Я пытаюсь создать HTTP-перехватчик в Angular 4, но у меня есть какая-то странная ошибка. Ниже приведена моя ошибка:

Argument of type 'Observable<Response>' is not assignable to parameter of type 'Observable<Response>'.

Ниже приведен мой код:

import { Injectable } from '@angular/core';
import { Http, ConnectionBackend, RequestOptions, RequestOptionsArgs } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import * as _ from 'lodash';

@Injectable()
export class HttpInterceptor extends Http {

    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router) {
        super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.request(url, options)); // Here is the error
    }

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.get(url, options)); // Here is the error
    }

    post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.post(url, body, this.getRequestOptionArgs(options))); // Here is the error
    }

    put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.put(url, body, this.getRequestOptionArgs(options))); // Here is the error
    }

    delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return this.intercept(super.delete(url, options)); // Here is the error
    }

    getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
        if (options == null) {
            options = new RequestOptions();
        }
        if (options.headers == null) {
            options.headers = new Headers(); // Here is the error
        }
        options.headers.append('Content-Type', 'application/json');
        return options;
    }

    intercept(observable: Observable<Response>): Observable<Response> {
        return observable.catch((err, source) => {
            if (err.status == 401 && !_.endsWith(err.url, 'api/auth/login')) {
                this._router.navigate(['/login']);
                return Observable.empty();
            } else {
                return Observable.throw(err);
            }
        });

    }

}

Ответы

Ответ 1

Перехватчик Http уже реализован в Angular 4.3.4 и описан в документации.

Вам нужно реализовать метод intercept интерфейса HttpInterceptor, сделать что-то с запросом и вызвать метод next.handle(req).

import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';

@Injectable()
export class NoopInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const changedReq = req.clone({headers: req.headers.set('My-Header', 'MyHeaderValue')});
    return next.handle(changedReq);
  }
}

Также необходимо зарегистрировать раздел перехватчика в разделе поставщиков приложений

import {NgModule} from '@angular/core';
import {HTTP_INTERCEPTORS} from '@angular/common/http';

@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: NoopInterceptor,
    multi: true,
  }],
})
export class AppModule {}

Ответ 2

Ответ akn правильный. Я пытался заставить его работать с сервисом http, но перехватчик работает только с сервисом whit httpClient.

import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) { }

Ответ 3

Доступные во всем мире типы DOM ("lib": ["dom"] в вашем tsconfig) включают в себя интерфейсы Response и Request, которые не связаны с типами, используемыми Angular.

Вам нужно импортировать Response и Request из @angular/http.

Ответ 4

Следующая инструкция отлично работала для меня:

В модуле приложения:

import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { myInterceptor} from './Interceptors/myInterceptor';

@NgModule({
    imports: [
...
    HttpClientModule,
  ],
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: MyInterceptor,
    multi: true
  }],
  bootstrap: [AppComponent]
})

В перехватчике:

import { Injectable } from '@angular/core';

import {
  HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse
} from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import { HttpErrorResponse } from '@angular/common/http';
import { RequestOptions } from '@angular/http';
import { HttpHeaders } from '@angular/common/http';

@Injectable()
export class MyInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // when there is POST request
    if (req.method === 'POST') {
      const content_type = 'application/x-www-form-urlencoded';
      const req= req.clone({
        headers: req.headers.set('Content-Type', content_type),
        body: 'my body'
      });

      return next.handle(accessReq);
    }
  }
}

ВАЖНО: http должен быть экземпляром HttpClient!

constructor(
    private http: HttpClient, private accessTokenService: AccessTokenService
) { }
    return this.http.post(ingestURL, null)
        .map(res => {
            return res; // data returned from interceptor
        });