Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Http response do not include headers #5237

Closed
bpquintanilha opened this issue Nov 11, 2015 · 53 comments
Closed

Http response do not include headers #5237

bpquintanilha opened this issue Nov 11, 2015 · 53 comments
Labels

Comments

@bpquintanilha
Copy link

@bpquintanilha bpquintanilha commented Nov 11, 2015

Maybe i am doing something wrong but when i make a request with Http i can see on the Network tab on chrome that the response include a custom header called 'Authorization' used to refresh the JWT. But when i try to access the response.headers it prints empty on the console.

return this.http.request(req).map((res: Response) => console.log(res.headers.values()));

image

the same behaviour when printing keys().

the request headers, on the other hand, do print all the custom headers i add to the request.

@bpquintanilha
Copy link
Author

@bpquintanilha bpquintanilha commented Nov 11, 2015

Hey guys, i have found where the problem is and changed to get what i need.

In Http.dev.js on line 10645 aprox. i have added this basic snipet:

var arrayOfLines = _xhr.getAllResponseHeaders().match(/[^\r\n]+/g);
          var headers = new headers_1.Headers();
          for(var i = 0; i < arrayOfLines.length; i++){
            var line = arrayOfLines[i];
            var name = line.substr(0,line.indexOf(':')).trim();
            var val = line.substr(line.indexOf(':')+1).trim();

            headers.append(name,val);
          }

          responseOptions.headers = headers;

sorry i did not do it in typescript because i was lazy to recompile.

also, of course, had to add the headers to the dependencies array and required it. I hope it helps.

EDIT
As the release 2.0.0-alpha.46 came out, the location changed. Still at the XHRConnection but the Http.dev.js has changed and now it is at line 721.

In xhr_backend.ts, XHRConnection class line 18.

Thanks

@cangosta
Copy link

@cangosta cangosta commented Nov 12, 2015

Hi all, I'm having this same issue in alpha.44. I can't access the response header information that are supposed to be present in the headers map of the response. Example:

var req = new Request({
  url: `localhost/api/products`,
  method: RequestMethods.Get
});

this.http.request(req).subscribe(
  res => {
    // Can't access the headers of the response here.... res.headers is empty
  },
  error => { ... },
  _ => {}
);

If I check the network traffic in the browser's dev tools, the response headers are present...

@bpquintanilha
Copy link
Author

@bpquintanilha bpquintanilha commented Nov 12, 2015

See my edit. I have a workaround to this issue untill they fix it.

Hope it helps you

@cangosta
Copy link

@cangosta cangosta commented Nov 13, 2015

Hi @bruno-quintanilha, thanks for your suggestion.

After some diving into angular2 code (and yours too), I realize that not all response headers are present when I invoke _xhr.getAllResponseHeaders(). Actually, only a couple of them are present!

Here follow the real response headers:

image

And the result of the _xhr.getAllResponseHeaders():

"Content-Language: pt-PT Content-Type: application/json; charset=utf-8"

Are there any suggested workaround?

@bpquintanilha
Copy link
Author

@bpquintanilha bpquintanilha commented Nov 13, 2015

Hi there,

try access directly to your custom header with: _xhr.getResponseHeader('x-total-count');

Maybe some checking if it exists.

But i can tell you that i am able to access all response headers with the previous sugestion.

Still, does this value really needs to be a header? cant you send it with the response and a custom Http class (extend it or encapsulate) to intercept the response and separate that value from the real response?

Hope it helps

@bpquintanilha
Copy link
Author

@bpquintanilha bpquintanilha commented Nov 13, 2015

BTW. Aqui da ilha da Madeira! @cangosta

robwormald added a commit to robwormald/angular that referenced this issue Nov 20, 2015
robwormald added a commit to robwormald/angular that referenced this issue Nov 20, 2015
robwormald added a commit to robwormald/angular that referenced this issue Nov 20, 2015
Properly parse and add response Headers to Response.

Closes angular#5237
robwormald added a commit to robwormald/angular that referenced this issue Nov 20, 2015
Properly parse and add response Headers to Response.

Closes angular#5237
robwormald added a commit to robwormald/angular that referenced this issue Nov 20, 2015
Properly parse and add response Headers to Response.

Closes angular#5237
robwormald added a commit to robwormald/angular that referenced this issue Nov 20, 2015
Properly parse and add response Headers to Response.

Closes angular#5237
@tbragaf
Copy link

@tbragaf tbragaf commented Dec 7, 2015

Hi all!

My custom headers are not being retrieved, for they do not appear it the headers map...

Anyone with the same problem?

tbragaf

@machi1990
Copy link

@machi1990 machi1990 commented Dec 7, 2015

I have the same problem. Tried the workaround, with no success.

@robwormald
Copy link
Contributor

@robwormald robwormald commented Dec 8, 2015

we're simply grabbing headers from the raw XHR object, so if they don't appear there, there's not a whole lot we can do about it, unless there's something else we're missing. for those having issues, if you do a manual XHR request (see: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest ) - are you able to access the headers you're looking for?

@tbragaf
Copy link

@tbragaf tbragaf commented Dec 8, 2015

My API was used in an NG1 app, so yes.
Also it was tested with this: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

tbragaf

@machi1990
Copy link

@machi1990 machi1990 commented Dec 8, 2015

I am using the alpha46, and still not able to retrieve the response headers. Testing my WS with the REST Client, response headers are there. I can even see them in the browser developer's console, but not just on the my angular2 response object.

@tbragaf
Copy link

@tbragaf tbragaf commented Dec 8, 2015

Alpha46 doesnt Support headers on response, it is a bug.
Still nothing with alpha48

@machi1990
Copy link

@machi1990 machi1990 commented Dec 8, 2015

Ah I see. I had an issue with RxJs when upgrading to alpha48, so I have not tried it yet. As of current, I am still on alpha46 and retrieving the headers using the fetch API while waiting for the bug fix.

@robwormald
Copy link
Contributor

@robwormald robwormald commented Dec 9, 2015

@tbragaf http://plnkr.co/edit/FJj4Zqze6xpBCcH2M5Bl?p=preview <- this is with alpha 50, and i believe has been like this since 46 or 47. Could you look at the plunker please and see if you're doing things differently?

@tbragaf
Copy link

@tbragaf tbragaf commented Dec 9, 2015

@robwormald Make sure you test this under the limit of 24 hours :)
http://plnkr.co/edit/V6RkITHxtwOLiwWJlezI?p=preview

The result should be x-total-count: 42

That header is not present, but you can see it if you go to the "Network" tab.

@robwormald If you confirm this, can you please re-open the issue?

@robwormald
Copy link
Contributor

@robwormald robwormald commented Dec 9, 2015

I can confirm they don't appear, but as I said above, its not something we have any control over. See this demo using vanilla XMLHttpRequest: http://plnkr.co/edit/u2YWls1U5Rw5eS74CQWA?p=preview

That throws an error : Refused to get unsafe header "x-total-count" - note that is the browser rejecting access, outside of angular entirely.

@tbragaf
Copy link

@tbragaf tbragaf commented Dec 10, 2015

@robwormald
Adding 'access-control-expose-headers' : 'x-total-count' on the API solves it :)

Thank you,
tbragaf

@robwormald
Copy link
Contributor

@robwormald robwormald commented Dec 10, 2015

👍

@jppellerin
Copy link

@jppellerin jppellerin commented Feb 4, 2016

yup! Thanks @tbragaf. That's the issue I was having.

@albanx
Copy link

@albanx albanx commented Aug 11, 2016

Maybe it can help. My solution was to add this in the backend, the Access-Control-Expose-Headers made the trick:

...
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Custom-header");
header("Access-Control-Expose-Headers: X-Custom-header");
header("X-Custom-header: $some data");

Then on front end this worked fine:

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

@amin-RFarzin amin-RFarzin commented Nov 8, 2016

The trick is to use "Access-Control-Expose-Headers"
(e.g., <response-header name="Access-Control-Expose-Headers" header-name="Access-Control-Expose-Headers" header-value="accept, authorization, content-type, x-requested-with, jwt"/>)

@rmunozfu
Copy link

@rmunozfu rmunozfu commented Apr 17, 2017

@shuforov shuforov mentioned this issue Apr 19, 2017
@ymallikreddy521
Copy link

@ymallikreddy521 ymallikreddy521 commented May 23, 2017

Hi.

Fixed by adding below code in webapi controller.
returnValue.Content.Headers.Add("x-filename", "File.doc");
returnValue.Content.Headers.Add("access-control-expose-headers", new[] { "x-filename" });

@shivarajnaidu
Copy link

@shivarajnaidu shivarajnaidu commented Feb 21, 2018

How can i get the full response object...?

 this.http.get(url, options)
  .toPromise()
  .then(data => {
     console.log(data) // getting response body but not response object with headers and body
   })
@trotyl
Copy link
Contributor

@trotyl trotyl commented Feb 21, 2018

@shivarajnaidu https://angular.io/guide/http#reading-the-full-response

this.http.xxx(url, { observe: 'response' })
@bhupal4all
Copy link

@bhupal4all bhupal4all commented May 28, 2018

How Can I read Response Header (Content-Disposition)?

When I check at either Postman or Google Chrome Network tab, I can see 'Content-Disposition' at the response headers section, but NOT able to read at Angular Code.

// Node - Server JS
app.get('/download', function (req, res) {
  var file = __dirname + '/db.json';
  res.set({
    'Content-Type': 'text/plain',
    'Content-Disposition': 'attachment; filename=' + req.body.filename
  })
  res.download(file); // Set disposition and send it.
});


// Angular5 Code

 saveFile() {
    const headers = new Headers();
    headers.append('Accept', 'text/plain');
    this.http.get('http://localhost:8090/download', { headers: headers })
      .subscribe(
        (response => this.saveToFileSystem(response))
      );
  }

  private saveToFileSystem(response) {
    const contentDispositionHeader: string = response.headers.get('Content-Disposition'); // <== Getting error here, Not able to read Response Headers
    const parts: string[] = contentDispositionHeader.split(';');
    const filename = parts[1].split('=')[1];
    const blob = new Blob([response._body], { type: 'text/plain' });
    saveAs(blob, filename);
  }

@bhupal4all
Copy link

@bhupal4all bhupal4all commented May 29, 2018

Thanks @trotyl , I set 'Access-Control-Expose-Headers' at Node Js Server and am able to read 'Content-Disposition' at Angular code.

@rsbrum
Copy link

@rsbrum rsbrum commented Jun 20, 2018

In case there still is someone having trouble with this, I'll leave my solution for both the backend and frontend.

Heres how you set the headers: https://github.com/rsbrum/NodeJS-RESTAPI-JWTAuth/blob/master/jwt-auth.js

Heres how you access the header on the client side: https://github.com/rsbrum/Angular6-JWT-Auth/blob/master/src/app/shared/interceptor/interceptor.service.ts

@bhumin3i
Copy link

@bhumin3i bhumin3i commented Sep 21, 2018

i'm getting error while send x-auth-token in header.

import { Http, Headers, RequestOptions } from '@angular/http';
  if (token != ''){
            
              this.global.headerData['x-access-token'] = token; //allow get data from server 
  this.global.headerData['x-auth-token'] = token; //this is not allow give me error **Response with status: 0 for URL: null**
            } 
              
            let headers = new Headers(this.global.headerData);
            let options = new RequestOptions({ headers: headers });
 this.http.get(url, options)
@santiagomolinadecastro
Copy link

@santiagomolinadecastro santiagomolinadecastro commented Oct 3, 2018

I have the same problem. I'm invoking an Identity Server service and i hope that it return Authorization header. This header is coming ok but from JavaScript when i make getAllResponseHeaders i can't get it.

Then, i found this topic and reading it, i tried send Expose-Headers:

req.setRequestHeader('Access-Control-Expose-Headers', 'Authorization');

But i get the same result:

"pragma: no-cache
cache-control: no-cache, no-store, max-age=0, must-revalidate
expires: 0
"

It not returns authorization header. Can you helpme with another idea?

Thanks!!

@trotyl
Copy link
Contributor

@trotyl trotyl commented Oct 3, 2018

@santiagomolinadecastro Access-Control-Expose-Headers is a response header, not request header. It must be set on the same response of where Authorization is.

@santiagomolinadecastro
Copy link

@santiagomolinadecastro santiagomolinadecastro commented Oct 3, 2018

Thanks for your help @trotyl

@santiagomolinadecastro
Copy link

@santiagomolinadecastro santiagomolinadecastro commented Oct 3, 2018

The question is. Why i can see the header in my browser (in network section) and i can't see this header in my JavaScript code? The service returns that header but from JavaScript i can't get it. The question is, Why?

@trotyl
Copy link
Contributor

@trotyl trotyl commented Oct 3, 2018

@santiagomolinadecastro Because Web is designed to be secure, same reason for why I cannot get HTTP-only cookie in JavaScript.

@santiagomolinadecastro
Copy link

@santiagomolinadecastro santiagomolinadecastro commented Oct 3, 2018

@trotyl thanks!!!

@Waseem-farooqui
Copy link

@Waseem-farooqui Waseem-farooqui commented Oct 23, 2018

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;
  }));
@meitix
Copy link

@meitix meitix commented Nov 22, 2018

@pkozlowski-opensource Exactly, this is not an Angular issue. Is an API problem. With the header 'access-control-expose-headers' : 'name-of-expose-header' works fine.

The problem is that this doesn't work with the header 'access-control-expose-headers' : '*'. You can't use * and you have to put explicity the name of the headers that you want to expose.

it's working, god after 2 fucking days, just for the fucking header

@bhumin3i
Copy link

@bhumin3i bhumin3i commented Nov 23, 2018

@meitix @pkozlowski-opensource correct brother this is API problem.

@gabhiiaf93
Copy link

@gabhiiaf93 gabhiiaf93 commented Dec 12, 2018

I have got a fix,
try adding
{
"/api/v1/login": {
"target": "http://localhost:8000/api/v1/login",
"secure": false,
"logLevel": "debug",
"changeOrigin": "true"
}
}
in proxy.config.json and add the proxy config in the angular.json.
try running the application now and you will get the cookies if you have set cookie in the response headers

@nhhockeyplayer
Copy link

@nhhockeyplayer nhhockeyplayer commented Jan 15, 2019

meitix
please fix your language before you fix typescript

@kofindien
Copy link

@kofindien kofindien commented May 15, 2019

API (Node Js):
res.header("access-control-expose-headers", "name-of-expose-header");
res.setHeader('name-of-expose-header', "your-value");
Frontend(Angular):
response.headers.get('name-of-expose-header')

Ex: You can replace name-of-expose-header by etag.

@angular-automatic-lock-bot
Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Sep 15, 2019

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

You can’t perform that action at this time.