1

This is the way I add headers to an http-request in my Angular 4 application:

constructor(private http: Http) {    }

getUsers() {
    const headers = new Headers(
        {
            'Content-Type': 'application/json',
            'Authorization': 'somekey ' + localStorage.getItem('token')
        });
    return this.http.get(environment.apiUrl + 'users/all', {headers: headers})
}

My API works fine when I call it via Postman. And when I check the result of

request.getHeader("Authorization")

it returns back the proper value which is my token.

But when I call the API via frontend application

request.getHeader("Authorization")

returns null. And also creates a header named "access-control-request-headers" with this value: "authorization,content-type". Where is the token I set then? And why this request is not authorized to get the result just like when I call the API using Postman?

AliReza
  • 706
  • 2
  • 10
  • 30

2 Answers2

2

Try doing this.

private headers: Headers;

constructor(private http: Http) {
  this.headers = new Headers();
  this.headers.append('Content-Type', 'application/json');
  this.headers.append('Authorization', 'somekey ' + localStorage.getItem('token'));
}

public getUsers() {
  const options = new RequestOptions({
    headers: this.headers
  });
  return this.http.get(environment.apiUrl + 'users/all', options)
}
RKG
  • 592
  • 1
  • 7
  • 23
  • Thanks. Tried it. Still have the same problem. – AliReza Jul 21 '17 at 17:55
  • This is the "import" I used for the "header" object? import {Http, Headers, Response, RequestOptions} from '@angular/http' – AliReza Jul 21 '17 at 18:06
  • To rule out possible issues on the server side, can you try your GET call with a rest client like Postman? – RKG Jul 21 '17 at 18:06
  • Thats weird. I did not even know there was a different way to send http Headers in Angular2. All the examples I saw has the same exact way of doing it. – RKG Jul 21 '17 at 18:16
  • Check this example and thats exactly how its done. http://jasonwatmore.com/post/2016/08/16/angular-2-jwt-authentication-example-tutorial. Not really sure what's wrong with your setup. – RKG Jul 21 '17 at 18:20
  • Agree with you, it's weird. Thank's for the link! – AliReza Jul 21 '17 at 18:45
  • After debugging the backend and inspecting the HttpServletRequest I realized that the header title is added. I found "content-type, authorization" as the value of "access-control-request-headers" but couldn't find the value of them. Now I am even more confused! Do you have any idea where can I see the value of these headers? Does it mean the headers and their values are set? – AliReza Jul 24 '17 at 23:53
  • Based on what you said, it looks like your headers are being set when the request is sent to the server. For some reason, your server does not seem to accept the Headers being sent. Its been ages I worked on Java and dont remember a great deal about HttpServletRequest. Can you print `request.getHeader("Authorization");`? – RKG Jul 25 '17 at 14:38
  • You could may be try this. `Enumeration headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()) { String headerName = (String)headerNames.nextElement(); out.println("Header Name: " + headerName); out.println("Header Value: " + request.getHeader(headerName)); }` – RKG Jul 25 '17 at 14:40
  • Thank you Rama for all the information. The result of request.getHeader(""access-control-request-headers") is "authorization,content-type". But the result of request.getHeader("authorization") is null. And when I call the API via Postman, request.getHeader("authorization") returns the token! To me, that means the header is not set yet but I have no idea why my code is just setting the value for "access-control-request-headers" header and not "Authorization" and "Content-type" headers. – AliReza Jul 25 '17 at 15:25
  • This seems very challenging to solve, so I did some digging on this and found this. https://github.com/angular/angular/issues/6583. I hope this helps. – RKG Jul 25 '17 at 15:38
1

It was a CORS (Cross-Origin Resource Sharing) problem causing by the browser's mechanism. And I believe it's not a matter of frontend framework.

There are two different types of requests: Simple Requests and Preflighted Requests.

When you add new headers to a request, it won't be counted as a simple request anymore. And Unlike “simple requests”, "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this, since they may have implications to user data.

Like the simple requests, the browser adds the Origin header to every request, including the preflight. The preflight request is made as an HTTP OPTIONS request. It also contains a few additional headers and "Access-Control-Request-Headers" is one of those additional headers which is a comma-delimited list of non-simple headers that are included in the request. In my case the value of this header is: "authorization,content-type".

So, the request I was inspecting was the preflighted one not the actual-request I was sending to the backend-API.

You may deal with this preflighted request in your own way. Just like avoid filtering and set status 200 when http method is OPTIONS:

if("options".equalsIgnoreCase(request.getMethod())) {
    response.setStatus(HttpServletResponse.SC_OK);
} else {
    chain.doFilter(req, res);
}

Which might not be the best solution but you won't get "Response for preflight has invalid HTTP status code 401".

Please let me know what is your preferred way to deal with this preflighted request

Here are the links I used to shape this answer. They can help you to learn more about CORS:

https://www.html5rocks.com/en/tutorials/cors/

http://restlet.com/company/blog/2015/12/15/understanding-and-using-cors/

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Response for preflight has invalid HTTP status code 401 - Spring

AliReza
  • 706
  • 2
  • 10
  • 30