How to extend angular 2 http class in Angular 2 final

前端 未结 6 1198
别跟我提以往
别跟我提以往 2020-12-09 03:39

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

相关标签:
6条回答
  • 2020-12-09 03:48

    From Angular 4.3, we don't need to extends http anymore. Instead, we can use HttpInterceptor and HttpClient to archive all these stuffs.

    It's similar and easier than using Http.

    I migrated to HttpClient in about 2 hours.

    Detail is here

    0 讨论(0)
  • 2020-12-09 03:54

    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.

    0 讨论(0)
  • 2020-12-09 03:57

    You can actually just extend the Http in your own class and then the only use a custom factory to provide Http as that:

    then in my App Providers I was able to use a custom Factory to provide 'Http'

    import { RequestOptions, Http, XHRBackend} from '@angular/http';

    class HttpClient extends Http {
     /*
      insert your extended logic here. In my case I override request to
      always add my access token to the headers, then I just call the super 
     */
      request(req: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    
          options = this._setCustomHeaders(options);
          // Note this does not take into account where req is a url string
          return super.request(new Request(mergeOptions(this._defaultOptions,options, req.method, req.url)))
        }
    
      }
    }
    
    function httpClientFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions): Http {
    
      return new HttpClient(xhrBackend, requestOptions);
    }
    
    @NgModule({
      imports:[
        FormsModule,
        BrowserModule,
      ],
      declarations: APP_DECLARATIONS,
      bootstrap:[AppComponent],
      providers:[
         { provide: Http, useFactory: httpClientFactory, deps: [XHRBackend, RequestOptions]}
      ],
    })
    export class AppModule {
      constructor(){
    
      }
    }
    

    with this approach you don't need to override any of the Http function you do not wish to change

    0 讨论(0)
  • 2020-12-09 03:59

    Check out my article on how to extend the Http class for Angular 2.1.1

    First, lets create our custom http provider class.

    http.service.ts
    
    import {Injectable} from '@angular/core';
    import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http';
    import {Observable} from 'rxjs/Observable';
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/catch';
    
    @Injectable()
    export class HttpService extends Http {
    
      constructor (backend: XHRBackend, options: RequestOptions) {
        let token = localStorage.getItem('auth_token'); // your custom token getter function here
        options.headers.set('Authorization', `Bearer ${token}`);
        super(backend, options);
      }
    
      request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
        let token = localStorage.getItem('auth_token');
        if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
          if (!options) {
            // let's make option object
            options = {headers: new Headers()};
          }
          options.headers.set('Authorization', `Bearer ${token}`);
        } else {
        // we have to add the token to the url object
          url.headers.set('Authorization', `Bearer ${token}`);
        }
        return super.request(url, options).catch(this.catchAuthError(this));
      }
    
      private catchAuthError (self: HttpService) {
        // we have to pass HttpService's own instance here as `self`
        return (res: Response) => {
          console.log(res);
          if (res.status === 401 || res.status === 403) {
            // if not authenticated
            console.log(res);
          }
          return Observable.throw(res);
        };
      }
    }
    

    Now, we need to configure our main module to provide the XHRBackend to our custom http class. In your main module declaration, add the following to the providers array:

    app.module.ts

    import { HttpModule, RequestOptions, XHRBackend } from '@angular/http';
    import { HttpService } from './services/http.service';
    ...
    @NgModule({
      imports: [..],
      providers: [
        {
          provide: HttpService,
          useFactory: (backend: XHRBackend, options: RequestOptions) => {
            return new HttpService(backend, options);
          },
          deps: [XHRBackend, RequestOptions]
        }
      ],
      bootstrap: [ AppComponent ]
    })
    

    After that, you can now use your custom http provider in your services. For example:

    user.service.ts

    import { Injectable }     from '@angular/core';
    import {HttpService} from './http.service';
    
    @Injectable()
    class UserService {
      constructor (private http: HttpService) {}
    
      // token will added automatically to get request header
      getUser (id: number) {
        return this.http.get(`/users/${id}`).map((res) => {
          return res.json();
        } );
      }
    }
    
    0 讨论(0)
  • 2020-12-09 04:00

    I think peeskillet's answer should be the selected answer, so what I'm putting here is only meant to augment his answer as opposed to compete with it, but I also wanted to provide a concrete example since I don't think it's 100% obvious exactly what code peeskillet's answer translates to.

    I put the following in the providers section of my app.module.ts. I'm calling my custom Http replacement MyHttp.

    Notice how, like peeskillet said, it would be provide: Http, not provide: MyHttp.

      providers: [
        AUTH_PROVIDERS
        {
          provide: Http,
          useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
            return new MyHttp(backend, defaultOptions);
          },
          deps: [XHRBackend, RequestOptions]
        }
      ],
    

    Then my Http-extending class is defined like this:

    import { Injectable } from '@angular/core';
    import { Http } from '@angular/http';
    
    @Injectable()
    export class MyHttp extends Http {
      get(url: string, options?: any) {
        // This is pointless but you get the idea
        console.log('MyHttp');
        return super.get(url, options);
      }
    }
    

    Nothing special needs to be done in order for your app to use MyHttp instead of Http.

    0 讨论(0)
  • 2020-12-09 04:13

    You can check https://www.illucit.com/blog/2016/03/angular2-http-authentication-interceptor/ which will help you.

    Change your providers as below for latest release and check it :

    providers: [
      {
        provide: SecureHttpService,
        useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
          return new SecureHttpService(backend, defaultOptions);
        },
        deps: [ XHRBackend, RequestOptions]
      },
      Title
    ]
    
    0 讨论(0)
提交回复
热议问题