Angular 2/4 如何将多个标题添加到 http post

Posted

技术标签:

【中文标题】Angular 2/4 如何将多个标题添加到 http post【英文标题】:Angular 2/4 how to add multiple headers to http post 【发布时间】:2017-11-24 01:31:19 【问题描述】:

我在向 html 帖子添加附加标题时遇到了问题。 curl 和 postman 一样工作得很好。 我无法将授权标头添加到发布请求。

我的问题类似于https://***.com/questions/39408413/angular2-http-post-how-to-send-authorization-header

我的代码:

 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()

)  

现在,当我尝试获取这个时,没有添加这两个标题

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

但是当我评论 Authorization 标头时,会添加 Content-Type 并且会出现错误 400 的 get invalid_client

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

但是当我评论 Content-Type 标头并附加授权时,我遇到了与第一次相同的问题 - 没有添加标头:/

我有 angular 4.2 - 从 ng cli 安装和升级

如何在 POST 中添加附加标题?在 Postman 中这项工作非常完美

===== 已编辑 ==== 感谢您的回复,但两种解决方案都不起作用

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()
) 

现在,如果我评论 'Authorization' Content-Type 被添加到带有 AUthorization 的请求中,我不会添加任何标头并且也不会发送正文

=========已编辑=========

根据这个话题Angular2 - set headers for every request我已经创建了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 ;

在 app.module.ts 中

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

现在为我服务

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()
      ) 

  

我仍然有错误:/没有添加标题:/

我进行了一些调查、测试。当我尝试仅发送“Content-type=application/x-www-form-urlencoded”时,我收到错误“错误客户端”的回复,因为我没有发送授权。当我尝试使用授权添加另一个标头时出现问题。

我用 GET 方法做了类似的事情,我只能添加“授权”标题,没有其他。如果我添加例如“X-Authorization”标头,则 GET 方法将更改为 OPTIONS 方法,如 POST :/

在控制台我得到错误:

XMLHttpRequest 无法加载 https://accounts.spotify.com/api/token。 对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:4200” 访问。

有没有办法在 http post 请求的一个标头中提供更多?

我只添加了带有正文的 Content-Type 标头。我收到了 400 代码的回复,因为我的请求没有 Authorization 标头。在 Firefox 中,我通过向标头添加授权来编辑此请求,我得到了我想要的带有令牌的代码 200 :) 所以问题出在 Angular 而不是浏览器上。

==== 已编辑 ==== Spotify 说我不应该使用 clientid 和 client+secret。我应该使用这个:

 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)
          
        )

现在我得到 200,但未显示回调。在控制台中我有:

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.

这来自“回调:1”

我已经为回调和回调组件制定了路线

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

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


但在控制台中我仍然有错误:/

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.

但这一次来自 'localhost/:1

在邮递员中,我使用完整的 html 进行重定向。如何在 Angular 2 中进行此重定向

【问题讨论】:

我们可以注意到,当我尝试添加 Authorization 标头时,请求方法更改为 OPTIONS 而不是 POST :/ 我读到了 CORS,就是这样。当我尝试添加非标准 Header xhr 时,首先使 OPTIONS 方法询问允许的标题,但 api spotify 不接受 POST 方法上的 OPTIONS。 CURL 直接发送所有标头,因此有很好的答案。有什么办法可以防止 xhr ro 在 POST 之前发送 OPTIONS 方法吗? 你能解决你的问题吗?我猜你的代码手动添加标题并使用默认标题工作,问题出在服务器上配置的 CORS(你没有 cURL 问题,因为它不关心来源)。因此,当您在浏览器中发布帖子时,它首先会发送一个 OPTIONS 请求(称为预检)。服务器对其进行检查。如果没问题,您的浏览器将收到 OK 响应,然后发送 POST 请求。如果服务器不允许该请求,您的浏览器将从 OPTIONS 请求中收到错误消息。 @nicram 你的问题解决了吗?因为我有同样的问题,你能分享你为解决问题所做的工作吗> 【参考方案1】:

好吧,如果您使用的是最新的 Angular HttpClient,这很容易。请参阅示例。

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

希望对您有所帮助。谢谢

【讨论】:

【参考方案2】:

您可以利用 Interceptors 在每个请求上放置标头:

本教程将帮助您实现这一目标:

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

【讨论】:

感谢您的回答。这就是我想要的 太棒了! @nicram,如果您将此设置为选定的问题,我将不胜感激,亲爱的! 本教程中的示例是 Angular 4.3 及更高版本的肉类,使用从 '@angular/common/http' 导入的 HttpClient。【参考方案3】:

我所做的和工作是这样的

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

我在请求中使用this.options

希望对你有帮助

【讨论】:

哪个角度版本? 5? 当时是4.3,所以不是HttpClient【参考方案4】:

你可以这样设置标题

 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');

另外,在 Angular 5 中 新课程介绍让您可以轻松设置

header = new HttpHeaders();
header.set('Content-Type', 'application/x-www-form-urlencoded');

【讨论】:

【参考方案5】:

在不使用new Headers() 的情况下将多个标头添加到 http 帖子的一种方法如下:

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

希望对你有帮助。

【讨论】:

以上是关于Angular 2/4 如何将多个标题添加到 http post的主要内容,如果未能解决你的问题,请参考以下文章

在angular2中向FormGroup添加多个验证器

如何在 Angular 中使用多个 ViewChild 元素 (2/4)

如何将 Angular 2/4 应用程序部署到网络托管?

将 jQuery 插件添加到 Angular 应用程序

如何使用 Angular JS 处理表单中的多个提交按钮?

如何将数据绑定到 Angular 2 中的多个嵌套组件?