3

I've problem with adding additonal headers to html post. with curl works very well like with postman. I can't add Authorization header to post request.

my problem is similar to https://stackoverflow.com/questions/39408413/angular2-http-post-how-to-send-authorization-header

my code:

 getToken(){

let headers = new Headers;
headers.append('Authorization', 'Basic ' + btoa(Spotify.clientId + ':' + Spotify.clientSecret));
headers.append('Content-Type', 'application/x-www-form-urlencoded');

let options = new RequestOptions({ headers: headers });


let params = new URLSearchParams();
params.append('grant_type', 'client_credentials');

 console.log(

  this.http.post(Spotify.tokenUrl, params.toString(), options).subscribe()

)  
}

Now, when I try to get this none of those two headers aren't added

OPTIONS /api/token HTTP/1.1
Host: accounts.spotify.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://172.21.7.171:4200
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, 
  like Gecko) Chrome/59.0.3071.86 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */ *
Referer: http://172.21.7.171:4200/
Accept-Encoding: gzip, deflate, br
Accept-Language: pl,en;q=0.8,en-US;q=0.6

But when I comment Authorization header, Content-Type is added and a get invalid_client with error 400

POST /api/token HTTP/1.1
Host: accounts.spotify.com
Connection: keep-alive
Content-Length: 29
Accept: application/json, text/plain, */ *
Origin: http://172.21.7.171:4200
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, 
 like Gecko) Chrome/59.0.3071.86 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://172.21.7.171:4200/
Accept-Encoding: gzip, deflate, br
Accept-Language: pl,en;q=0.8,en-US;q=0.6

But when I comment Content-Type header and append Authorization I have the same issue like first time - no added header :/

I'have angular 4.2 - installed and upgraded from ng cli

How to add additonal headers to POST? in Postman this work perfect

enter image description here

===== Edited ==== Thanks for reply, but both solutions don't work

getToken(){

let options = new RequestOptions();
  options.headers = new Headers();
  options.headers.append('Authorization', Spotify.token);
  options.headers.append('Content-Type', 'application/x-www-form-urlencoded')

let params = new URLSearchParams();
params.append('grant_type', 'client_credentials');

 console.log(
  this.http.post(Spotify.tokenUrl, params.toString(), options).subscribe()
) 
}

now if I comment 'Authorization' Content-Type is added to Request with AUthorization i none header isn't added and body isn't sent too

========= edited =========

According to this topic Angular2 - set headers for every request I've created default-request-options.service.ts

import { Injectable } from '@angular/core';
import { BaseRequestOptions, RequestOptions, Headers } from '@angular/http';

@Injectable()
export class DefaultRequestOptions extends BaseRequestOptions {

    private superHeaders: Headers;

    get headers() {
        // Set the default 'Content-Type' header
        this.superHeaders.set('Content-Type', 'application/json');

        const token = localStorage.getItem('authToken');
        if(token) {
            this.superHeaders.set('Authorization', `Bearer ${token}`);
        } else {
            this.superHeaders.delete('Authorization');
        }
        return this.superHeaders;
    }

    set headers(headers: Headers) {
        this.superHeaders = headers;
    }

    constructor() {
        super();

    }
}

export const requestOptionsProvider = { provide: RequestOptions, useClass: DefaultRequestOptions };

in app.module.ts

import { requestOptionsProvider, DefaultRequestOptions } from './default-request-options.service'
...
providers: [
    requestOptionsProvider
  ],

now in my service

import { DefaultRequestOptions } from '../default-request-options.service';
  getToken(){

    let params = new URLSearchParams();
    params.append('grant_type', 'client_credentials');

    let options = new DefaultRequestOptions();
      //options.headers = new Headers();
     // options.headers.append('Authorization', Spotify.basicCode);
      //options.headers.append('Content-Type', 'application/x-www-form-urlencoded');
      // options.body = params.toString();
      // options.method = 'post';

   console.log(
      this.http.post(Spotify.tokenUrl, params.toString(), options).subscribe()
      ) 

  }

And I have errors still :/ Headers aren't added :/

I've made some investigations, tests. When I try send only 'Content-type=application/x-www-form-urlencoded' I get reply with error 'bad client' because I don't send Authorization. Problem occours when I try to add another header with Authorization.

I've made similar with GET method and I can add only 'Authorization' header, none other. If I added for example "X-Authorization" header that GET method is changed to OPTIONS method like in POST :/

In console I get error:

XMLHttpRequest cannot load https://accounts.spotify.com/api/token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

Is there any way to provide more in one header in http post request?

I added only Content-Type header with body. I got reply with 400 code because my request was without Authorization header. In firefox I edited this reqest by adding Authorization to headers and I got what I wanted code 200 with token :) So the problem is with Angular not with browser.

==== EDITED ==== Spotify says that i shouldn't use clientid and client+secret. i should use this:

 let options = new RequestOptions()
      options.headers = new Headers();
      options.params = new URLSearchParams();
      options.params.append('client_id', Spotify.clientId);
      options.params.append('redirect_uri', 'http://localhost:4200/callback');
      options.params.append('scope', 'user-read-private user-read-email');
      options.params.append('response_type', 'token');
      options.params.append('state', '789935');

this.http.get('https://accounts.spotify.com/authorize', options )
        .subscribe(
          res=> {
            console.log('res',res)
          }
        )

now i get 200 but callback isnt displayed. in console i have:

XMLHttpRequest cannot load https://accounts.spotify.com/authorize?client_id=2100FakeClientId45688548d5a2b9…scope=user-read-private%20user-read-email&response_type=token&state=789935. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

and this comes from "callback:1"

I've made route for callback and callbackComponent

import { Component } from '@angular/core';
// import { AuthService } from './auth.service';

@Component({
  template: `<h2>callback</h2>`
})
export class CallbackComponent {

}

but in console I've error still :/

localhost/:1 XMLHttpRequest cannot load https://accounts.spotify.com/authorize?client_id=21006d1ceeFakeClient548d5a2b9…scope=user-read-private%20user-read-email&response_type=token&state=789935. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

but this time this comes from 'localhost/:1

In postman I het full html to redirect. How can I make this redirection in Angular 2

user276648
  • 6,018
  • 6
  • 60
  • 86
nicram
  • 353
  • 3
  • 7
  • 24
  • As We can notice, when I try to add Authorization header then request method is changed to OPTIONS instead of POST :/ – nicram Jun 21 '17 at 09:47
  • 2
    I read about CORS and this is it. When I try to add non standard Header xhr first make OPTIONS method to ask about allowed headers but api spotify doesn't acctept OPTIONS on POST methods. CURL sends directly all headers so there is good answer. Is there any way to prevent xhr ro sent OPTIONS method befor POST? – nicram Jun 22 '17 at 12:21
  • Were you able to fix your problem? I guess your code to manually add headers and to use default headers work, the problem is with CORS, which is configured on the Server (you don't have issues with cURL because it doesn't care about the origin). So when you do the post in your browser, it first sends an OPTIONS request (it's called the preflight). The server checks it. If it's fine, your browser will receive an OK response and then will send the POST request. If the server doesn't allow the request, your browser will get an error from the OPTIONS request. – user276648 Oct 31 '17 at 02:25
  • @nicram is your issue resolved? because i have same issue, can you plz share what you did to resolve issue> – Abhijit Jagtap Jan 06 '18 at 09:02

5 Answers5

12

Well, if you are using latest angular HttpClient, it is very easy. See the example.

this.httpClient.post(url, body, {
      headers: new HttpHeaders().set('Authorization', 'Bearer ' + this.getAuthAccessToken())
      .set('Content-Type', 'application/json') 
    })

Hope it helps. Thanks

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141
Tanver Hasan
  • 1,687
  • 13
  • 12
2

You can make use of Interceptors to put headers on every request:

This tutorial will help you accomplish that:

https://medium.com/codingthesmartway-com-blog/angular-4-3-httpclient-accessing-rest-web-services-with-angular-2305b8fd654b

NaN
  • 8,596
  • 20
  • 79
  • 153
  • Thanks for Your answer. This is what I wanted – nicram Nov 21 '17 at 18:38
  • 1
    Great! @nicram, if you please set this as the selected question I would appreciate very much, my dear! – NaN Nov 22 '17 at 12:53
  • The example in the tutorial is meat for Angular 4.3 and above with use of HttpClient imported from '@angular/common/http'. – NaN Nov 22 '17 at 12:53
1

What I do and works is that

  this.options = new RequestOptions({
    headers: new Headers({
      'header1': 'value1',
      // And more
    })
  });

And I use this.options in my requests.

Hope this helps you

1

you can set header like that

 let options = new RequestOptions();
    options.headers = new Headers();
    options.headers.append('Authorization', 'Basic ' + btoa(Spotify.clientId + ':' + Spotify.clientSecret));
    options.headers.append('Content-Type', 'application/x-www-form-urlencoded');

Also, in Angular 5 new class introduce so you can set easily

header = new HttpHeaders();
header.set('Content-Type', 'application/x-www-form-urlencoded');
Shailesh Ladumor
  • 7,052
  • 5
  • 42
  • 55
0

One way to add multiple headers to http post without using new Headers() would be the following:

$http.post(url, entity, {
    headers: {
      customHeader1: customHeader1Value,
      customHeader2: customHeader2Value
    }
  }).then(...

I hope it helps.

MarioC
  • 81
  • 1
  • 6