Angular HttpClient无法获取响应头

53

我最近在学习Angular。 我有一个分页请求。

const myParams = new HttpParams().set('page', page.toString()).set('size', size.toString());
this.http.get<HttpResponse<User[]>>('https://localhost:8443/user/', {
      headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
      params: myParams,
      observe: 'response'
    }).suscribe((response: HttpResponse<User[]>) => this.data = response.body);

数据库中元素的总数通过 X-Total-Count 头信息传递给客户端。我试图这样读取它:

.suscribe((response: HttpResponse<User[]>) => {
    this.data = response.body;
    this.totalCount = response.headers.get('X-Total-Count');
});

但是这并不起作用。结果发现response.headers仅包含真实http响应头的一个子集。
这就是headers对象的样子。
"headers": {
    "normalizedNames": {},
    "lazyUpdate": null
  }

我确信 X-Total-Count 已经发送。Firefox 开发者工具可以显示它。请问如何将其包含在响应中?

enter image description here

更新

这个问题与被识别为重复的问题不同,区别在于:我并没有询问如何检查完整的httpResponse。我自己解决了这个问题。我一直在问的是为什么Responseheaders属性不完整。


3
很抱歉告诉您,这不是您提到的帖子的复制品。正如您所看到的,我使用了您链接答案中的方法:observe: 'response'。我的问题是,response.headers并没有包含后端发送的所有标头。 - Mr.H.
对不起,你是正确的! - Tsvetan Ganev
5个回答

112

CORS请求仅公开6个安全列表头:Cache-Control Content-Language Content-Type Expires Last-ModifiedPragma

为了使用CORS请求访问自定义标头,服务器必须显式地将它们列入白名单。这可以通过发送响应标头实现:Access-Control-Expose-Headers

例如: Access-Control-Expose-Headers: X-Total-Count, X-Paging-PageSize

MDN来源


5
大啊,我刚从一个坑里爬出来。感谢你的回答。如果你正在使用Flask CORS,只需设置公开标头选项,就可以了。 - activedecay
3
在我的情况下,我在ASP.NET Core服务器端添加了这个CORS策略设置services.AddCors(o => o.AddPolicy("CorsPolicy", builder => { builder .AllowAnyHeader() .WithOrigins(origins) .WithExposedHeaders(new string[] { "X-Total-Count" }) .AllowCredentials(); })); - John McCann
1
对于那些想要在(.NET 6)ASP.NET Web API中添加这些头部的人,请在CORS策略上使用.WithExposedHeaders("X-Total-Count")。 - Quido

25
在HttpResponse对象中,头部信息是惰性加载的,因此在强制加载这些值之前,headers看起来是空的。尝试调用response.headers.keys()以查看所有可用的标头名称。顺便说一句,这也会将所有值强制加载到映射response.headers.headers中。

1
如果您没有使用CORS,则这是正确的答案。如果我可以投更多票,我一定会的!!! - Lee Willis

2
尝试在http选项对象中添加withCredentials: true。原始答案被翻译成"最初的回答"。

2

如Tsvetan Ganev之前所述,如果这是CORS请求,则需要按名称在Access-Control-Expose-Headers标头中显式公开所需的标头。要实现此目的,您需要配置应用程序服务器,例如在使用WebMvcConfigurer时,您可以公开标题:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")
                .allowedOrigins("*")
                .exposedHeaders("X-Total-Count")
                .allowedMethods("*");
    }
}

使用此配置后,您的浏览器将除了7个默认头之外,还会暴露X-Total-Count头部信息,这七个默认头是:
  • Cache-Control
  • Content-Language
  • Content-Length
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma
请注意,本文中出现的HTML标签应该保留。

0
在我的情况下,Postman 能够获取自定义的 "Authorization" 标头,但 Angular 却不能。我通过显式地公开自定义标头来解决了这个问题。
@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    // vvv
    config.addExposedHeader(HttpHeaders.AUTHORIZATION);
    // ^^^
    config.addAllowedMethod(HttpMethod.OPTIONS);
    config.addAllowedMethod(HttpMethod.GET);
    config.addAllowedMethod(HttpMethod.POST);
    config.addAllowedMethod(HttpMethod.PUT);
    config.addAllowedMethod(HttpMethod.PATCH);
    config.addAllowedMethod(HttpMethod.DELETE);
    config.setMaxAge(1800L);
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

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