Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 disable XSRFStrategy for a single service or per request

Tags:

angular

I fetch results from third party REST services in my application. These services stall with Request header field X-XSRF-TOKEN is not allowed by Access-Control-Allow-Headers in preflight response. because angular2 has set this header as a standard for all requests per default.

I've figured out how to disable this:

import { HttpModule, XSRFStrategy } from '@angular/http';

export class NoXSRFStrategy {
  configureRequest(req: Request) {
    // Remove `x-xsrf-token` from request headers
  }
}
@NgModule({
  imports: [
    HttpModule
  ],
  declarations: [ ],
  providers: [{ provide: XSRFStrategy, useFactory: () => new NoXSRFStrategy() }] // !!HACK!!
})
export class AppModule { }

But this works on a module level, meaning it disables this for all requests regardless of which service provides them.

What I would like, is to decide for my self which Http call that should be stripped of such headers and which can continue using them. With the solution above, I have to isolate the service in a separate module and use the NoXSRFStrategy for only this module. I haven't tested this in conjunction with other services in other modules, but I hope this does not set NoXSRFStrategy as a global request config.

Just to illustrate what I would like to be possible:

@Injectable()
export class MyService {

  constructor(private http: Http) { }
  apiCall() {
    return this.http.get('some.online/service.json', {useXsrf: false}); // ...or something... IDK
  }

Or perhaps on service level:

@Injectable()
export class MyService {

  constructor(private http: Http) { 
    this.http.setXsrfStrategy(NoXSRFStrategy); // For only this http instance...
  }

Does anybody know if there is any way of disabling the X-XSRF-TOKEN header other than setting a module level config?

like image 754
Øystein Amundsen Avatar asked Nov 25 '16 11:11

Øystein Amundsen


1 Answers

I figured it out!

You can override the default Http class with your own. This is the closest I got to a Http Interceptor:

app.module.ts

@NgModule({
  declarations: [AppComponent],
  imports: [HttpModule],
  providers: [{ provide: Http, useClass: AuthHttp }],
  bootstrap: [AppComponent]
})
export class AppModule { }

AuthHttp.ts

import {Injectable} from '@angular/core';
import {Http, Request, Response, RequestOptionsArgs, RequestOptions, XHRBackend} from '@angular/http';
import {Router} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/throw';

@Injectable()
export class AuthHttp extends Http {
  constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);

    // Setup default http headers here
    defaultOptions.headers.append('Cache-control', 'no-cache');
    defaultOptions.headers.append('Cache-control', 'no-store');
    defaultOptions.headers.append('Pragma', 'no-cache');
    defaultOptions.headers.append('Expires', '0');
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    // Before request execution. You can manipulate headers per request here.

    return super.request(url, options)
      .map(res => { // Successful Response
        return res;
      })
      .catch((err: any) => { // Unsuccessful Response.
        return Observable.throw(err);
      });
  }
}
like image 180
Øystein Amundsen Avatar answered Oct 14 '22 04:10

Øystein Amundsen