14

I'm using the code below to try to extract a value (ReturnStatus) from the response headers;

Keep-Alive: timeout=5, max=100
ReturnStatus: OK,SO304545
Server: Apache/2.4.29 (Win32) OpenSSL/1.0.2m

The code;

import { Injectable } from '@angular/core';

import { Account } from './model/account';
import { HttpClient } from '@angular/common/http';
import { Observable, throwError } from "rxjs";
import { map, filter, catchError, mergeMap } from 'rxjs/operators';

 createOrder(url) : Observable<any> {

  return this._http.get(url, {withCredentials: true, observe: 'response'})
  .pipe(
    map((resp: any) => {
      console.log("response", resp);
      return resp;

    }), catchError( error => {
      console.log("createOrder error",error );
      alert("Create Order Service returned an error. See server log for mote details");
    return throwError("createOrder: " + error)

    })
  );
}

However my console.log just give;

HttpResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: 
"http://localhost/cgi-bin/dug.cgi/wh?Page… 
plateLocation=C:%5Ctemp%5Corderimporttemplate.txt", ok: true, …}

I've looked on this site and others for the correct way to do this in Angular but to no avail? Could someone point me in the right direction please?

Many thanks,

Mark.

2
  • what is your problem? where do you try to get response status and it fails?
    – firegloves
    Commented Jun 21, 2018 at 13:10
  • it doesn't fail as such I'm just trying to find the correct way to get to the ReturnStatus line in the response header. Commented Jun 21, 2018 at 13:27

1 Answer 1

27

You need to observe the entire response as described below:

 createOrder(url) : Observable<HttpResponse<Object>>{

    return this.http.get<HttpResponse<Object>>(this.url, {observe: 'response'}).pipe(
         tap(resp => console.log('response', resp))
    );
}

Now inside resp you can access headers An example

 createOrder(url) : Observable<HttpResponse<Object>>{

    return this.http.get<HttpResponse<Object>>(this.url, {observe: 'response'}).pipe(
         tap(resp => console.log('heaeder', resp.headers.get('ReturnStatus')))
    );
}

If you can't access your custom header as explained above it's because a small set of headers are exposed to javascript by default for security reasons. Probably if you open developer tools and you inspect your response headers you should see the desired one.

Who can choose which headers are exposed to javascript?

Exposed headers are choosen by the web application (so your webservices, or your backend. Obviously you web application could be written using many languages and/or using many framework.

Depending on what you are using you can achieve this goal by different ways.

To give you an idea of what you should do I can post my Spring solution. In class extending WebSecurityConfigurerAdapter you should add this two methods:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            // we don't need CSRF because our token is invulnerable
            .csrf().disable()
            .cors()
} 


@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addExposedHeader("Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
            "Content-Type, Access-Control-Request-Method, Custom-Filter-Header");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("DELETE");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

Note that I've disabled csrf because I'm using JWT. Note that you should refine CorsFilter rules.

As you can see I have added Custom-Filter-Header into this line

config.addExposedHeader("Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
                "Content-Type, Access-Control-Request-Method, Custom-Filter-Header");

You can replace this Custom-Filter-Header with your ReturnStatus

7
  • Hi. Thanks for this. Unfortunately it looks like there maybe something else required also as this is a custom header? github.com/angular/angular/issues/5237 details adding "Access-Control-Expose-Headers" to the API... Commented Jun 21, 2018 at 14:35
  • let me know if you are not using spring, if I can I should help you to solve your backend troubles :)
    – firegloves
    Commented Jun 21, 2018 at 16:39
  • Very much appreciate the offer of help for this issue. For the moment we've coded around it by returning an XML response and parsing that instead Commented Jun 22, 2018 at 8:11
  • 1
    key thing inside config - observe: "response" as 'body'. pipe tap is redundant
    – Dima V
    Commented Aug 27, 2018 at 12:20
  • If anyone is using CORS and ASP.NET on the server, you have to explicitly expose the header value with the exposedHeaders parameter when you configuring CORS. Commented Dec 26, 2018 at 7:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.