123

I'm triggering a HTTP request and I'm getting a valid response from it. The response also has a header X-Token that I wish to read. I'm trying the below code to read the headers, however, I get null as a result

this.currentlyExecuting.request = this.http.request(reqParams.type, reqParams.url, {
    body: reqParams.body,
    responseType: 'json',
    observe: 'response'
}).subscribe(
    (_response: any) => {
        // Also tried _response.headers.init();
        const header = _response.headers.get('X-Token');
        console.log(header);
        onComplete(_response.body);
     },
    _error => {
        onComplete({
            code: -1,
            message: Constants.WEBSERVICE_INTERNET_NOT_CONNNECTED
        });
    }
);

The response of the API, when checked in Chrome inspect, shows the header is present.

enter image description here

6
  • 5
    have you expose the x-token from server side? using "access-control-expose-headers". because not all headers are allowed to be accessed from the client side, you need to expose them from the server side. Commented Jan 10, 2018 at 9:30
  • 8
    If he has it in the console, then yes, he exposed it. Commented Jan 10, 2018 at 9:37
  • 2
    @HrishikeshKale: You are right. Access-Control-Expose-Headers worked. You may post this as an answer. Commented Jan 10, 2018 at 9:48
  • i have posted this as an answer. happy coding :) Commented Jan 10, 2018 at 10:01
  • 6
    trichetriche, I don't agree. I had a situation where I was adding the header on the server and could see it in the browser console, but the browser code couldn't see it. I had to explicitly mark it to be exposed (in my server code) to the browser because of CORS. Commented Dec 26, 2018 at 7:43

9 Answers 9

204

Have you exposed the X-Token from server side using access-control-expose-headers? because not all headers are allowed to be accessed from the client side, you need to expose them from the server side

Also in your frontend, you can use new HTTP module to get a full response using {observe: 'response'} like

http
  .get<any>('url', {observe: 'response'})
  .subscribe(resp => {
    console.log(resp.headers.get('X-Token'));
  });
Sign up to request clarification or add additional context in comments.

12 Comments

is it same for post method also... i am getting error "Request header field observe is not allowed by Access-Control-Allow-Headers in preflight response."
Where can I read more about this? This fixed my problem but I'd like to know what's going on
@KaiCriticallyAcclaimedCooper yes sure here is the link html5rocks.com/en/tutorials/cors also, there is Github issue github.com/angular/angular/issues/6583
I still have problem to read Headers , I found the answer , see this: stackoverflow.com/questions/58601675/…
I could see the header in postman. Does it mean header is exposed or not? I am not getting that header when i use above code @HrishikeshKale
|
29

In my case in the POST response I want to have the authorization header because I was having the JWT Token in it. So what I read from this post is the header I we want should be added as an Expose Header from the back-end. So what I did was added the Authorization header to my Exposed Header like this in my filter class.

response.addHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Access-Control-Allow-Headers", "Authorization, X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept, X-Custom-header");
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token); // HEADER_STRING == Authorization

And at my Angular Side

In the Component.

this.authenticationService.login(this.f.email.value, this.f.password.value)
  .pipe(first())
  .subscribe(
    (data: HttpResponse<any>) => {
      console.log(data.headers.get('authorization'));
    },
    error => {
      this.loading = false;
    });

At my Service Side.

return this.http.post<any>(Constants.BASE_URL + 'login', {username: username, password: password},
  {observe: 'response' as 'body'})
  .pipe(map(user => {
       return user;
  }));

Comments

22

You should use the new HttpClient. You can find more information here.

http
  .get<any>('url', {observe: 'response'})
  .subscribe(resp => {
    console.log(resp.headers.get('X-Token'));
  });

1 Comment

what should be URL here?
17

As Hrishikesh Kale has explained we need to pass the Access-Control-Expose-Headers.

Here how we can do it in the WebAPI/MVC environment:

protected void Application_BeginRequest()
        {
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                //These headers are handling the "pre-flight" OPTIONS call sent by the browser
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:4200");
                HttpContext.Current.Response.AddHeader("Access-Control-Expose-Headers", "TestHeaderToExpose");
                HttpContext.Current.Response.End();
            }
        }

Another way is we can add code as below in the webApiconfig.cs file.

config.EnableCors(new EnableCorsAttribute("", headers: "", methods: "*",exposedHeaders: "TestHeaderToExpose") { SupportsCredentials = true });

**We can add custom headers in the web.config file as below. *

<httpProtocol>
   <customHeaders>
      <add name="Access-Control-Expose-Headers" value="TestHeaderToExpose" />
   </customHeaders>
</httpProtocol>

we can create an attribute and decore the method with the attribute.

Happy Coding !!

Comments

11

You can get data from post response Headers in this way (Angular 6):

import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
  observe: 'response' as 'response'
};

this.http.post(link,body,httpOptions).subscribe((res: HttpResponse<any>) => {
  console.log(res.headers.get('token-key-name'));
})

Comments

2

You can get headers using below code

let main_headers = {}
this.http.post(url,
  {email: this.username, password: this.password},
  {'headers' : new HttpHeaders ({'Content-Type' : 'application/json'}), 'responseType': 'text', observe:'response'})
  .subscribe(response => {
    const keys = response.headers.keys();
    let headers = keys.map(key => {
      `${key}: ${response.headers.get(key)}`
        main_headers[key] = response.headers.get(key)
       }
      );
  });

later we can get the required header form the json object.

header_list['X-Token']

Comments

1

Angular 7 Service:

    this.http.post(environment.urlRest + '/my-operation',body, { headers: headers, observe: 'response'});
    
Component:
    this.myService.myfunction().subscribe(
          (res: HttpResponse) => {
              console.log(res.headers.get('x-token'));
                }  ,
        error =>{
        }) 
    

Comments

1

Try this simple code.

1. Components side code: to get both body and header property. Here there's a token in body and Authorization in the header.

loginUser() {
    this.userService.loginTest(this.loginCred).
    subscribe(res => {
        let output1 = res;
        console.log(output1.body.token);
        console.log(output1.headers.get('Authorization'));
    })
}

2. Service side code: sending login data in the body and observe the response in Observable any which be subscribed in the component side.

loginTest(loginCred: LoginParams): Observable<any> {
    const header1= {'Content-Type':'application/json',};
    const body =  JSON.stringify(loginCred);
    return this.http.post<any>(this.baseURL+'signin',body,{
        headers: header1,
        observe: 'response',
        responseType: 'json'
    });
}

Comments

0

I had to do the following to get the headers to appear in SPA Angular application when GETting them from ASP.NET Core service:

var builder = WebApplication.CreateBuilder(args);

services.AddCors(options =>
{
    options.AddPolicy("MyExposeResponseHeadersPolicy",
        builder =>
        {
            builder.WithOrigins("https://*.example.com")
                   .WithExposedHeaders("x-custom-header");
        });
});

builder.Services.AddControllers();

var app = builder.Build();

1 Comment

That was really useful... I had no idea that we would be able to see the Header values on the Chrome "Network" tab, but without this addition, the Angular app wouldn't be able to "see" the Header values.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.