vigamage
vigamage

Reputation: 2125

Adding headers to HTTP requests conditionally using RequestOptions

In my Angular2 application, I am setting header values to each and every request using CustomRequestOptions class which extends BaseRequestOptions.

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
    constructor(private _globals: Globals) {
        super();
        this.headers.set('Content-Type', 'application/json');
        this.headers.set('X-Requested-By', 'Angular 2');
    }

    merge(options?: RequestOptionsArgs): RequestOptions {

        // can I access the headers here I have set when the request is made ?
        // and then conditionally set Content-Type 

        var newOptions = super.merge(options);
        let hdr = this._globals.getAuthorization();

        newOptions.headers.set("Authorization", hdr);

        return newOptions;
    }

}

As you can see, Content Type is set to application/json.

Now I have a requirement to upload a photo to the server. The Content type has to be cleared for that request only.

The way I thought of using is setting some header value to the request, getting that value inside merge method and conditionally clear the content type header.

Setting a custom header when the request is declared:-

let formData: FormData = new FormData();
formData.append('file', photoToSave);

let headers = new Headers();
//setting a custom header
headers.append('from', 'photo-upload');
let options = new RequestOptions();
options.headers = headers;

let savedPath = this._http
    .post(this._endpointUrl + "save-photo", formData, options)
    .map(
    res => {
        return res.json();
    }
    )
    .catch(handleError);

Accessing the added header in merge method. This is where I have the problem. Can I do what I am trying to do. ? I tried following as a starting point. But the accessed headers are null. See the comment in the code.

 merge(options?: RequestOptionsArgs): RequestOptions {

    console.log("options header = " + options.headers); //this prints null
    console.log("options body = " + options.body);

    var newOptions = super.merge(options);

    if(from header equal to 'photo-upload'){
      newOptions.headers.set('Content-Type', '');
    }else{
       newOptions.headers.set('Content-Type', 'application/json');
    }

    let hdr = this._globals.getAuthorization();
    newOptions.headers.set("Authorization", hdr);

    return newOptions;
}

Now my question is about the validity of what I am trying to do. If it is not valid, please point me out a way to do this. Thank You..!

Upvotes: 0

Views: 3148

Answers (2)

vigamage
vigamage

Reputation: 2125

I was able to resolve the issue by storing a variable from in local storage of the browser instead of adding it as a header. This variable is assigned the name "photo-upload". (Whatever the name you prefer)

then, the next time the merge method is called, that from variable is checked. If it contains the value "photo-upload", I just ignore. If it does not equal to "photo-upload" I set the header value newOptions.headers.set('Content-Type', 'application/json');

 if(localStorage.get("from") === "photo-upload"){
    newOptions.headers.set('Content-Type', '');
 }else{
    newOptions.headers.set('Content-Type', 'application/json');
 }

Upvotes: 0

Karan Patel
Karan Patel

Reputation: 2289

For this stuff, You can create one base service and inside that servce, You can set header for every API request.

BaseService file:

import { Injectable } from "@angular/core";
import { Http, RequestOptions, Headers } from "@angular/http";

@Injectable()
export class BaseService {

    public apiUrl :string = 'your api url';

    constructor(private http: Http) {        
    }

    get(url: any) {

        return this.http.get(this.apiUrl + url).do(data => {
            console.log(data);
        });
    }

    post(url: any, data: any) {

        //Add uesr id every time for authentication
        if (data != null) {
            data.user_id = this.userId;
        }
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        try {
            return this.http.post(this.apiUrl + url, Json.serialize(data), options).do(data => {

                if (data != null && data.statusText != "No Content") {
                    console.log("Response Data - ", data.json());
                    //data.statusText ="No Content","OK";
                }
            });
        }
        catch (e) {
            console.log(e);
            return null;
        }
    }

}

APIService file:

import { Injectable } from "@angular/core";
import { Response } from "@angular/http";
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ApiService {

    constructor(public http: BaseService) {

    }

        //Toolbar
        public GetToolbarCollection(id: any): any {
            let data = {
                id: id
            };

            return this.http.post('GetToolbarCollection', data)
                .map((response: Response) => {
                    return new ToolbarCollection(response.json());
                })
                .catch(this.handleError);
        }

        public SetToolbarCollection(toolbarCollection: ToolbarCollection): any {

            let data = {
                toolbarCollection: toolbarCollection
            };

            return this.http.post('Portal/SetToolbarCollection', data)
                .map((response: Response) => {
                    return new ToolbarCollection(response.json());
                })
                .catch(this.handleError);
        }

        private handleError(error: Response) {
        HideLoader();
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }
}

In above code BaseService has two methods including get and set. Inside this ApiService I am using BaseService so every request will have custom header from base service.

Upvotes: 3

Related Questions