Custom service in extended Http not getting injected

572 views Asked by At

I want to extend the Http provider to intercept all requests that deliver a 403 status to handle an automatic logout. My custom InterceptingHttp should be declared as Http provider, so I don't need to care about a "special" http provider.

I have to following:

My custom Http provider

import { Injectable } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { AuthenticationService } from './../services/authentication.service';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class InterceptingHttpService extends Http {

    constructor(backend: XHRBackend, defaultOptions: RequestOptions, private authenticationService: AuthenticationService) {
    super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    var self = this;
    return super.request(url, options).catch((res: Response) => {
        if (res.status === 403) {
        console.log('intercepted');
        self.authenticationService.logout();
        }
        return Observable.throw(res);
    });
    }
}

The declaration as regular Http provider in NgModule

    @NgModule({
    imports: [
        BrowserModule,
        ToastyModule.forRoot(),
        HttpModule,
    FormsModule,
        routing,
        Ng2BootstrapModule,
    PaginationModule
    ],

    declarations: [
        AppComponent,
        NavHeaderComponent,
        FooterCopyrightComponent,
        InventoryRootComponent,
        InventoryTreeComponent,
        InventoryDetailComponent,
        SetModelComponent,
        MetadataListComponent,
        MetadataDetailComponent,
        ScriptGeneratorComponent,
        SetDetailComponent,
        SetVersionComponent,
        SetContainerTreeComponent,
        SetContainerDetailComponent,
        FilterByPropertyPipe,
        OrderContainersByLeafPipe,
        ResolveStateId,
        ConfirmComponent,
        FocusDirective
    ],
    providers: [
    SetService,
        SetTypeService,
        SetContainerService,
        StateService,
        NotificationService,
        MetadataService,
        MetadataTypeService,
        EntityService,
        SetContainerMetadataService,
    AuthenticationService,
    InterceptingHttpService,
        ConfirmService,
        SiteVersionService,
    {
        provide: Http,
        useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, authenticationService: AuthenticationService) => {
        return new InterceptingHttpService(backend, defaultOptions, authenticationService);
        },
        deps: [XHRBackend, RequestOptions, AuthenticationService]
    },
    ],
    bootstrap: [AppComponent]
})

It gets loaded and it does intercept all 403 responses. The only odd thing is, that the authenticationService is undefined.

I guess I'm probably do a mistake in my providers declaration. I tried to add AuthenticationService to the deps array, which only resulted into an Circular dependency error.

Where is my mistake? How can I use my AuthenticationService in my extended Http provider?

1

There are 1 answers

5
Günter Zöchbauer On BEST ANSWER

You need to add AuthenticationService to deps

deps: [XHRBackend, RequestOptions, AuthenticationService]

When Http is injected to AuthenticationService this will cause a circular dependency that DI can't resolve.

See DI with cyclic dependency with custom HTTP and ConfigService for an approach how to work around circular dependency.