How to extend angular 2 http class in Angular 2 final

mezhik91 picture mezhik91 · Sep 24, 2016 · Viewed 20.1k times · Source

I'm trying to extent angular 2 http class to be able to handle global errors and set up headers for my secureHttp service. I found some solutions but it doesn't work with final release of Angular 2. There is my code:

File: secureHttp.service.ts

import { Injectable } from '@angular/core';
import { Http, ConnectionBackend, Headers, RequestOptions, Response, RequestOptionsArgs} from '@angular/http';

@Injectable()
export class SecureHttpService extends Http {

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

File: app.module.ts

    import { BrowserModule, Title } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { routing } from './app.routes';
import { AppComponent } from './app.component';
import { HttpModule, Http, XHRBackend, RequestOptions } from '@angular/http';
import { CoreModule } from './core/core.module';
import {SecureHttpService} from './config/secure-http.service'

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    CoreModule,
    routing,
    HttpModule,
  ],
  providers: [
    {
      provide: Http,
      useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
        return new SecureHttpService(backend, defaultOptions);
      },
      deps: [ XHRBackend, RequestOptions]
    }, Title, SecureHttpService],
  bootstrap: [AppComponent],
})
export class AppModule { }

component.ts

constructor(private titleService: Title, private _secure: SecureHttpService) {}

  ngOnInit() {
    this.titleService.setTitle('Dashboard');
    this._secure.get('http://api.example.local')
        .map(res => res.json())
        .subscribe(
            data =>  console.log(data) ,
            err => console.log(err),
            () => console.log('Request Complete')
        );
  }

For now it returns me an error 'No provider for ConnectionBackend!'. Thanks for help!

Answer

Paul Samsotha picture Paul Samsotha · Sep 24, 2016

The reason for the error is because you are trying to provide SecureHttpService

providers: [SecureHttpService]

What this means is that Angular will try to create the instance, not using your factory. And it doesn't have a provider registered with the token ConnectionBackend to give to your constructor.

You could remove the SecureHttpService from the providers, but that will give you another error (which I'm guessing is why you added it in the first place). The error will be something like "no provider for SecureHttpService" because you are trying to inject it into your constructor

constructor(private titleService: Title, private _secure: SecureHttpService) {}

Here's where you need to understand about tokens. What you provide as the value to provide is the token.

{
  provide: Http,
  useFactory: ()
}

The token is what we are allowed to inject with. So you can instead inject the Http and it will use your created SecureHttpService. But this will take away any chance you have of using the regular Http, if you ever need it.

constructor(private titleService: Title, private _secure: Http) {}

If you don't need to know anything about the SecureHttpService, then you can leave it like this.

If you want to be able to actually inject the SecureHttpService type (maybe you need some API from it or maybe you want to be able to use the normal Http elsewhere), then just change the provide

{
  provide: SecureHttpService,
  useFactory: ()
}

Now you can inject both the regular Http and your SecureHttpService. And don't forget to remove the SecureHttpService from the providers.