如何在Angular 2中正确设置Http请求头

54

我的Ionic 2应用程序使用Angular 2,向ASP.NET Core API服务器发送Http PUT请求。这是我用来发送请求的方法:

public update(student: Student): Promise<Student>
{
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('authentication', `${student.token}`);

    const url = `${this.studentsUrl}`;

    return this.http
        .put(url, JSON.stringify(student), { headers: headers })
        .toPromise()
        .then(() => student)
        .catch(this.handleError);
}

我正在headers对象中设置身份验证的键/值。

但是当我在服务器上接收到此请求时,我无法在header中找到身份验证密钥:

enter image description here

正如您在图片中所看到的,header中有许多键,但是没有手动添加到客户端应用程序中的内容和身份验证键。

我做错了什么?


${student.token}student.token是相同的,但后者更简单。url变量也是如此。 - Evgeni Nabokov
请在此处查看: https://dev59.com/JVsW5IYBdhLWcg3w66qH#46684345 - Rajkeshwar Prasad
7个回答

80

你在http.put()请求选项中的参数实际上应该是RequestOptions类型。尝试像这样:

let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('authentication', `${student.token}`);

let options = new RequestOptions({ headers: headers });
return this.http
    .put(url, JSON.stringify(student), options)

8
“Type 'Headers' is not assignable to type 'Headers'”:/ 在 Angular 4 上无法工作。 (注:此错误信息可能需要更多上下文才能确定最准确的翻译,以上仅为可能的一种翻译方式。) - elporfirio
17
可以正常工作,你只需要正确导入 Headers: "import { Headers } from '@angular/http';" - Tim
1
我已经导入了import { Http, Response, RequestOptions, Headers } from '@angular/http';,但是在Angular 4中无法设置头文件。 - Suvonkar
1
@elporfirio 我已经添加了一个 Angular 4 的答案 - Brampage
@Suvonkar 我已经添加了一个 Angular 4 的答案 - Brampage
显示剩余2条评论

64

Angular 4 >

您可以选择手动设置标题,或创建一个HTTP拦截器,在每次请求时自动设置标题。


手动设置

设置标题:

http
  .post('/api/items/add', body, {
    headers: new HttpHeaders().set('Authorization', 'my-auth-token'),
  })
  .subscribe();

设置标题:

this.http
.post('api/items/add', body, {
  headers: new HttpHeaders({
    'Authorization': 'my-auth-token',
    'x-header': 'x-value'
  })
}).subscribe()

本地变量(不可变,再次实例化)

let headers = new HttpHeaders().set('header-name', 'header-value');
headers = headers.set('header-name-2', 'header-value-2');

this.http
  .post('api/items/add', body, { headers: headers })
  .subscribe()

HttpHeaders类是不可变的,因此每次调用set()方法都会返回一个新实例并应用更改。

来自 Angular 文档


HTTP 拦截器

@angular/common/http 的一个重要特性是拦截器(interception),即声明拦截器以位于应用程序和后端之间。当应用程序发出请求时,拦截器在将其发送到服务器之前转换它,而拦截器可以在返回响应之前对其进行转换,然后应用程序才能看到它。这对于从身份验证到日志记录等所有内容都很有用。

来自 Angular 文档

确保在整个应用程序中使用 @angular/common/http,这样您的请求将被拦截器捕获。

第一步,创建服务:

import * as lskeys from './../localstorage.items';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';

@Injectable()
export class HeaderInterceptor implements HttpInterceptor {

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (true) { // e.g. if token exists, otherwise use incomming request.
            return next.handle(req.clone({
                setHeaders: {
                    'AuthenticationToken': localStorage.getItem('TOKEN'),
                    'Tenant': localStorage.getItem('TENANT')
                }
            }));
        }
        else {
            return next.handle(req);
        }
    }
}

第二步,将其添加到您的模块中:

providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HeaderInterceptor,
      multi: true // Add this line when using multiple interceptors.
    },
    // ...
  ]

有用的链接:


1
请在您回答中的“手动”部分编写多个键值对的标题!谢谢! - Ankur Shah
1
@AnkurShah,我已经更新了我的答案,谢谢你的反馈。 - Brampage
当我不使用 HttpHeaders 时,结果很好,但是使用它会出现错误 TypeError: update.name.toLowerCase is not a function !! ...并且无法获取后端数据! - Ankur Shah
这应该可以工作,我测试过了。我的建议是从头开始重新创建一个简单的服务,使用@angular/common/http - Brampage
1
抱歉,现在它正在工作,我仍然在使用.set()!再次感谢!...由于响应延迟仍然存在一个错误,但那是另一个问题! - Ankur Shah
显示剩余2条评论

4

我们使用了这样一种解决方案:

this.http.get(this.urls.order + '&list', {
        headers: {
            'Cache-Control': 'no-cache',
        }
    }).subscribe((response) => { ...

点击这里参考相关的IT技术内容。


3
我们可以使用拦截器来优雅地完成它。您不必在所有服务中设置选项,也不必管理所有错误响应,只需定义2个拦截器(一个用于在将请求发送到服务器之前执行某些操作,另一个用于在将服务器的响应发送到您的服务之前执行某些操作)。
  1. 定义一个AuthInterceptor类,在发送请求到服务器之前做一些事情。您可以在这个类中设置api令牌(从localStorage检索,参见第4步)和其他选项。

  2. 定义一个responseInterceptor类,在将服务器响应发送到您的服务(httpClient)之前做一些事情。您可以管理您的服务器响应,最常见的用途是检查用户的令牌是否有效(如果无效,则清除localStorage中的令牌并重定向到登录页面)。

  3. 在您的app.module中导入HTTP_INTERCEPTORS自'@angular/common/http'。然后将拦截器(AuthInterceptor和responseInterceptor)添加到提供者中。这样做可以使您的应用程序在所有httpClient调用中考虑拦截器。

  4. 在登录http响应(使用http服务)时,将令牌保存在localStorage中。

  5. 然后为所有您的api rest服务使用httpClient

您可以在我的github项目 这里上查看一些良好的实践。

enter image description here


2
这个问题可以通过从Angular导入头文件来轻松解决:
import { Http, Headers } from "@angular/http";

2
@angular/http 已被弃用,自 Angular 4.3.x 及以上版本不应再使用!请改用 @angular/common/http(查看其他答案)! - Ankur Shah

0

您打错了一个字。

更改为:headers.append('Authentication', student.token);

请注意Authentication的首字母要大写。


3
但我认为Angular会自动将它转换为小写,对吗? - Pardeep Jain

0

给单个请求添加标头的更简单和当前的方法是:

// 步骤1

const yourHeader: HttpHeaders = new HttpHeaders({
    Authorization: 'Bearer JWT-token'
});

// POST 请求

this.http.post(url, body, { headers: yourHeader });

// GET 请求

this.http.get(url, { headers: yourHeader });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接