Axios如何获取响应头字段

322

我正在使用React和Redux构建前端应用程序,并使用axios执行请求。我想要访问响应头中的所有字段。在我的浏览器中,我可以检查标头并看到我需要的所有字段都存在(例如令牌,UID等),但是当我调用时...

const request = axios.post(`${ROOT_URL}/auth/sign_in`, props);
request.then((response)=>{
  console.log(response.headers);
});

我只得到

Object {content-type: "application/json; charset=utf-8", cache-control: "max-age=0, private, must-revalidate"}

这是我的浏览器网络标签页,你可以看到所有其他字段都存在。

enter image description here

最好的。


1
如果您打印axios.defaults.headers,是否会显示您缺少的任何内容?某些标头是在该级别配置的,而不是在每个请求的级别上(请参见https://github.com/mzabriskie/axios#global-axios-defaults)。 - Ben Hare
6
是不是axios.defaults.headers用于配置请求头参数?我需要访问响应头。@BenHare - TWONEKSONE
2
顺便提一句,你所谓的“request”并不是请求。它是你响应的承诺。你的请求是你作为参数传递给post()方法的内容。 - Daniel B
17个回答

543

针对CORS请求,浏览器默认只能访问以下响应头:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

如果您希望客户端应用程序能够访问其他响应头,您需要在服务器上设置Access-Control-Expose-Headers头。

Access-Control-Expose-Headers: Access-Token, Uid

1
对不起,我忘记将该字段暴露出来了。 - TWONEKSONE
42
如果您正在使用带有Rack-Cors的Rails,则需要在源上设置expose:['Access-Token','Uid'],例如:resource '*',:headers =>:any,:methods => [:get,:post,:put,:patch,:delete,:options,:head],expose:['Access-Token','Uid'] - CWitty
10
我不理解。如果它们没有暴露,为什么浏览器中可以看到额外的标题,但在axios响应中不能看到? - adanilev
14
浏览器允许您查看它们以进行调试,但出于安全原因,防止您通过API访问它们。这可以防止客户端从服务器获取安全凭据,使服务器确定客户端的访问权限。简而言之,这是出于安全目的而进行的。 - erfling
7
在我的 NGINX 配置文件中有这样一行代码:'Access-Control-Expose-Headers' 'Authorization, X-Suggested-Filename, content-disposition' always;仍然只能看到 content-type: "application/pdf"。非常需要获取 content-disposition - Old Man Walter
显示剩余3条评论

46

这真的帮助了我,谢谢Nick Uraltsev提供的答案。

对于那些使用nodejscors的人:

...
const cors = require('cors');

const corsOptions = {
  exposedHeaders: 'Authorization',
};

app.use(cors(corsOptions));
...

如果您采用以下方式发送响应:res.header('Authorization', `Bearer ${token}`).send();


3
对于那些想知道的人,你也可以在这里传递一个数组:exposedHeaders:['Authorization','X-Total-Count'] - Thiago Santana

20

我面临同样的问题。在我的WebSecurity.java 文件中,我尝试了这种方法,与 CORS 配置中的 setExposedHeaders 方法有关。


@Bean
CorsConfigurationSource corsConfigurationSource() {

    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowCredentials(true);
    configuration.setAllowedOrigins(Arrays.asList(FRONT_END_SERVER));
    configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
    configuration.setAllowedHeaders(Arrays.asList("X-Requested-With","Origin","Content-Type","Accept","Authorization"));
    
    // This allow us to expose the headers
    configuration.setExposedHeaders(Arrays.asList("Access-Control-Allow-Headers", "Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
            "Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"));
    
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

我希望它能够运作。


18

在ASP.NET Core中遇到了相同的问题,希望这可以帮到你。

public static class CorsConfig
{
    public static void AddCorsConfig(this IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                .WithExposedHeaders("X-Pagination")
                );
        });
    }
}

2
欢迎来到 Stack Overflow!您的答案可能是正确的,但在 Stack Overflow 上,不鼓励仅发布代码的回答。请尝试提供一份解释,说明您的答案如何解决原始问题。请阅读此处的更好的回答写作指南 - nircraft

7
根据官方文档
如果您想要得到服务器响应的HTTP头部信息,可以使用这个方法。所有的头部名称都是小写的,并且可以通过方括号访问。例如:response.headers['content-type']会返回类似于:headers: {} 的结果。

7
在使用axios进行CORS请求时,浏览器默认只能访问少数标头。
但是如果您需要从响应中访问自定义标头,则必须从您的后端服务器上发送带有Access-Control-Expose-Headers的响应。
以下是Node.js后端和React.js前端的示例:
res.header('Access-Control-Expose-Headers', 'x-xsrf-token');

return res.header("x-xsrf-token", token).status(200)
           .send({
                id: user.id,
                email: user.email,
            });

res.header('Access-Control-Expose-Headers', 'x-xsrf-token');

这行代码可以让我记录自定义的头信息,例如:

axios.post("/login", {
            email: emailInput.current.value,
            password: passwordInput.current.value,
        })
        .then(function (response) {

            console.log(response.headers["x-xsrf-token"]);

        });

如果在响应头中没有 Access-Control-Expose-Headers,则控制台日志会显示未定义。请检查网络选项卡中的响应头是否包含您自定义名称的标头。


7

这里还有一个提示,不在这次对话中。 对于 asp.net core 3.1, 首先添加你需要放入头部的密钥,类似以下形式:

Response.Headers.Add("your-key-to-use-it-axios", "your-value");

在定义CORS策略的位置(通常在Startup.cs中),您应该像这样将此键添加到WithExposedHeaders。

          services.AddCors(options =>
        {
        options.AddPolicy("CorsPolicy",
            builder => builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowAnyOrigin()
                .WithExposedHeaders("your-key-to-use-it-axios"));
        });
    }

在这里可以添加所有的密钥。 现在,在客户端中,你可以通过使用响应结果轻松访问 your-key-to-use-it-axios。

          localStorage.setItem("your-key", response.headers["your-key-to-use-it-axios"]);

您可以通过以下方式访问它,在所有客户端上使用:

const jwt = localStorage.getItem("your-key")

5

由于CORS限制,无法在客户端访问自定义HTTP标头。您需要在服务器端添加Access-Control-Expose-Headers设置。

什么是Access-Control-Expose-Headers?
请查看https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

默认情况下,只有这些HTTP标头可以公开:

  • Cache-Control
  • Content-Language
  • Content-Length
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

对于自定义HTTP标头,您需要在响应标头中自定义Access-Control-Expose-Headers。

如果您在服务器端使用Django,则可以使用django-cors-headershttps://pypi.org/project/django-cors-headers/)管理CORS设置。

例如,使用django-cors-headers,您可以通过CORS_ALLOW_HEADERS设置添加要向浏览器公开的HTTP标头列表。
from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = list(default_headers) + [
    'my-custom-header',
]


3

如果您在后端使用已正确配置CORS的Laravel 8,请将以下行添加到config/cors.php

'exposed_headers' => ['Authorization'],


1
谢谢您。我尝试使用通配符“*”,但它没有起作用,不过您的答案帮了我很大的忙。 - LuiKang

2

以下是一份清晰的步骤列表,以确保您无需像我一样整个晚上都在谷歌搜索。我将解决如何在axios的响应中读取授权头的问题。

对于后端,我正在使用标准的ExpressJS。我在Express中使用了cors()helmet()中间件,配置为空,但下面的方法仍然有效。

  1. 确保您的后端发送Access-Control-Expose-Headers。一开始将其设置为*以消除其他可能性。在Express中,可以这样设置:
res.setHeader('Access-Control-Expose-Headers', '*')

确保你的后端发送Access-Control-Allow-Headers。不要与第一步混淆,因为两者听起来很相似。将其设置为涵盖你想要读取的所有标头。以我的情况为例:
res.setHeader('Access-Control-Allow-Headers', 'Authorization,x-client-session')

在您的前端应用程序中,Axios将为标头返回“AxiosHeaders”类型。现在您应该已经暴露了您的标头。特别是对于授权,请使用:
const res = await axios(init)
const authHeader = res.headers.getAuthorization()

即使在最新的软件包版本中,您可能会遇到TypeScript错误:此表达式不可调用,但实际上是可调用的。
这就是它。

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