I'm trying to create HTTP Interceptor in Angular 4 but I'm having some weird error. Following is my error:
Argument of type 'Observable<Response>' is not assignable to parameter of type 'Observable<Response>'.
Following is my Code:
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);
}
});
}
}
Does anyone know what is going wrong here? I tried debugging for 3 hours but unable to find any clue.
Edit:
I also tried to remove everything and written a code like this:
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return super.request(url, options);
}
But still it's giving same error:
Argument of type 'string | Request' is not assignable to parameter of type 'string | Request'. Type 'Request' is not assignable to type 'string | Request'.
HTTP Interceptors is a special type of angular service that we can implement. It's used to apply custom logic to the central point between the client-side and server-side outgoing/incoming HTTP request and response. Keep in mind that the interceptor wants only HTTP requests.
To implement an interceptor, you'll want to create a class that's injectable and that implements HttpInterceptor. The intercept method takes two arguments, req and next, and returns an observable of type HttpEvent. req is the request object itself and is of type HTTP Request.
So how can I add multiple interceptors? Http doesn't allow to have more than one custom implementation. But as @estus mentioned the Angular team has added a new HttpClient service recently (release 4.3) which supports multiple interceptors concept. You don't need to extend the HttpClient as you do with the old Http .
Http interceptor is already implemented in Angular 4.3.4 and is described in the documentation.
You need to implement the intercept
method of HttpInterceptor
interface, do something with the request, and call the next.handle(req)
method.
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);
}
}
It's also necessary to register interceptor in app's providers section
import {NgModule} from '@angular/core';
import {HTTP_INTERCEPTORS} from '@angular/common/http';
@NgModule({
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: NoopInterceptor,
multi: true,
}],
})
export class AppModule {}
akn's answer is the right one. I was trying to make it work with http service, but the interceptor only works whit httpClient service.
import { HttpClient } from '@angular/common/http';
constructor(private http: HttpClient) { }
The globally available DOM typings ("lib": ["dom"]
in your tsconfig) include Response
and Request
interfaces that are unrelated to the types used by Angular.
You need to import Response
and Request
from @angular/http
.
The following instruction worked for me perfectly:
In the app module:
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]
})
In the interceptor:
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);
}
}
}
IMPORTANT: http should be an instance of HttpClient!
constructor(
private http: HttpClient, private accessTokenService: AccessTokenService
) { }
return this.http.post(ingestURL, null)
.map(res => {
return res; // data returned from interceptor
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With