21

i want to get session token in response header(Set-Cookie).how can i access values in Response header ?

var headers = new Headers();
            headers.append('Content-Type', 'application/json');
            console.log('url',this.loginUrl)
            this.http.post(this.loginUrl,
                JSON.stringify({ "username": value.username, "password": value.password }),
                { headers: headers })
                .map((res: Response) => 
                    res.json())
                .subscribe((res) => {
                    console.log("res", res);
                    this.loading.hide();
                    if (res.message_code == "SUCCESS") {
                        this.nav.setRoot(HomePage, {
                            username: value.username,
                        });
                    } else {
                        let alert =  Alert.create({
                            title: "Sign In Error !",
                            subTitle: 'Please Check Username or Password.',
                            buttons: ['Ok']
                        });
                        this.nav.present(alert);
                    }
                }, err => {
                    this.loading.hide();
                    console.log('error', err);

                }); 

this is my header response

enter image description here

hash
  • 5,336
  • 7
  • 36
  • 59

8 Answers8

26

The problem is that you map your response to its json content. Headers can be reached from the response itself. So you need to remove the map operator:

this.http.post(this.loginUrl,
       JSON.stringify({ "username": value.username, "password": value.password }),
       { headers: headers })
        /*.map((res: Response) =>  // <--------------
                res.json())*/
       .subscribe((res) => {
         var payload = res.json();
         var headers = res.headers;

         var setCookieHeader = headers.get('Set-Cookie')
         (...)
       });

Be careful with CORS with accessing the response headers. See this question:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • thanks for quick response.but `setCookieHeader ` give me a `null` value – hash Apr 05 '16 at 10:26
  • 1
    You're welcome! What is the content of the `Access-Control-Allow-Headers` of the preflighted options request? – Thierry Templier Apr 05 '16 at 10:27
  • in server side `origin, content-type, accept` from my app post request types are `x-requested-with` – hash Apr 05 '16 at 11:43
  • `headers.append("Access-Control-Allow-Headers", "x-requested-with");` – hash Apr 05 '16 at 11:43
  • hi any help about this question – hash Apr 06 '16 at 08:53
  • `HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Access-Control-Allow-Origin: http://localhost:8100 Vary: Origin Access-Control-Allow-Credentials: true Set-Cookie: JSESSIONID=3A8DA9A7DE3A41F980CC6C18A569BBCA; Path=/CRM_WEBSERVICE/; HttpOnly JSESSIONID: JSESSIONID=3A8DA9A7DE3A41F980CC6C18A569BBCA Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 06 Apr 2016 08:51:21 GMT` – hash Apr 06 '16 at 08:56
  • but in here i has `Set-Cookie` value – hash Apr 06 '16 at 08:57
  • 5
    Yes, but XHR (XMLHttpRequest) will skip headers that aren't specified in the `Access-Control-Allow-Headers` header in the context of cross domain requests (CORS) ;-) – Thierry Templier Apr 06 '16 at 09:01
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108375/discussion-between-kosala-and-thierry-templier). – hash Apr 06 '16 at 09:12
  • can you tell me how can i do that in java spring – hash Apr 06 '16 at 09:22
  • 1
    I don't know how your server application is implemented but I think that you could use the `allowedHeaders` method on the `CorsRegistry` class. This link could help you: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html. – Thierry Templier Apr 06 '16 at 09:32
  • .i modified my function with `headers.append("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); headers.append('Access-Control-Allow-Origin', '*');` the i got a `null` as value – hash Apr 06 '16 at 09:36
  • 1
    Yes but you have a preflighted request. So I guess that you need to do that on the implicite options method. That's why I think you need to do something with the spring cors support. Perhaps something can be done with annotations... – Thierry Templier Apr 06 '16 at 10:00
6

One way to solve that issue is to specify from your backend which one of the pairs {key: value} of your headers you want to expose.

Using a java backend, you can add the following lines:

public void methodJava(HttpServletResponse response){
...
response.addHeader("access-control-expose-headers", "Set-Cookie");
}

And now you can access this cookie element with your angular this way

service(){
...
return this.http
    .get(<your url here for your backend>)
    .map(res => console.log("cookie: " + res.headers.get("Set-Cookie") )
}

More explanation here

edkeveked
  • 17,989
  • 10
  • 55
  • 93
4

.map((res: Response) => { localStorage.setItem('setCookie', res.headers._headers.get("Set-Cookie")[0]); res.json() })

or you can take reference from https://angular.io/docs/ts/latest/api/http/index/Headers-class.html

Kanad Chourasia
  • 501
  • 4
  • 12
2

As described here

You need to set permission at producer side to access headers as -

header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Custom-header");
header("Access-Control-Expose-Headers: X-Custom-header");

And in angular you can do this -

this._http.get(url, options).toPromise()
            .then(res => {
                var data = res.headers.get('X-Custom-header');
                console.log(data);
                return res;
            })

Check it out.

Bopsi
  • 2,090
  • 5
  • 36
  • 58
1

You have to expose the headers on the server-side. Some headers are allowed to access from the client, like content-type, but not all. For more details have a look at paragraph: 'Access-Control-Expose-Headers (optional)' in http://www.html5rocks.com/en/tutorials/cors/

grueny
  • 81
  • 4
1

This stumped me for an hour. Although Chrome debugger shows the 'Location' header I was unable to read it in angular@4.3.3 using Microsoft.AspNetCore.Mvc 2.0.0

It turns out it was a CORS issue. The fix was a one liner in Startup.cs:

app.UseCors(builder =>
    builder.WithOrigins("https://mywebsite")
        .WithExposedHeaders("Location")  // <--------- ADD THIS LINE
        .AllowAnyHeader()
        .AllowAnyMethod());

And now I can read the header in angular:

this.authHttp.post('https://someapi/something', {name: 'testing'})
    .map((response: Response) => {
        // The following line now works:
        const url = response.headers.get('Location');
    });

I'm not sure how Chrome can see it but angular couldn't - it's obviously still part of the actual web api response.

mkaj
  • 3,421
  • 1
  • 31
  • 23
0

Another solution with Angular 4.2.+;

Service

getProfile(data) {
   return this.httpClient
      .request(new HttpRequest("POST", this.url, {}));
}

Component

this.userService.getProfile().subscribe(
  (response: any) => {
    if (response.type === HttpEventType.Response) {
      // response.headers is here
    }
  },
  (error: HttpErrorResponse) => {
    this.showMessage("error", "An error occurred");
  }
);
Rahmathullah M
  • 2,676
  • 2
  • 27
  • 44
-1

The answer is easy, just use the Location from url inside map function

.map((data: Response) => { response.url })
Dr. Lemon Tea
  • 549
  • 4
  • 13