Los axios obtienen acceso a los campos de encabezado de respuesta

161

Estoy creando una aplicación frontend con React y Redux y estoy usando axios para realizar mis solicitudes. Me gustaría tener acceso a todos los campos en el encabezado de la respuesta. En mi navegador puedo inspeccionar el encabezado y puedo ver que todos los campos que necesito están presentes (como token, uid, etc.), pero cuando llamo

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

Solo consigo

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

Aquí mi pestaña de red del navegador, como puede ver, todos los demás campos están presentes.

ingrese la descripción de la imagen aquí

Bests.

TWONEKSONE
fuente
Si imprime axios.defaults.headers, ¿le da alguno de los que falta? Algunos encabezados se configuran en ese nivel, no en el de cada solicitud (consulte github.com/mzabriskie/axios#global-axios-defaults )
Ben Hare
2
¿No es axios.defaults.headerspara configurar los parámetros del encabezado SOLICITAR? Necesito acceder a la RESPUESTA. @BenHare
TWONEKSONE
Por cierto, lo que llamó solicitud, no es una solicitud. Es una promesa para su respuesta. Su solicitud fue lo que pasó al método post () como argumentos.
Daniel

Respuestas:

312

En caso de solicitudes CORS, los navegadores solo pueden acceder a los siguientes encabezados de respuesta de forma predeterminada:

  • Control de caché
  • Lenguaje de contenido
  • Tipo de contenido
  • Expira
  • Última modificación
  • Pragma

Si desea que su aplicación cliente pueda acceder a otros encabezados, debe configurar el encabezado Access-Control-Expose-Headers en el servidor:

Access-Control-Expose-Headers: Access-Token, Uid
Nick Uraltsev
fuente
Lo malo fue que olvidé exponer esos campos.
TWONEKSONE
28
Si está utilizando Rails con Rack-Cors, debe establecer expose: ['Access-Token', 'Uid']el origen como:resource '*', :headers => :any, :methods => [:get, :post, :put, :patch, :delete, :options, :head], expose: ['Access-Token', 'Uid']
CWitty
3
No lo entiendo Si no están expuestos, ¿por qué los encabezados adicionales son visibles en el navegador pero no en la respuesta axios?
adanilev
44
@adanilev, los navegadores le permiten verlos con fines de depuración, pero le impiden acceder a ellos a través de API por razones de seguridad. Impide que los clientes obtengan credenciales seguras de los servidores, lo que permite al servidor determinar qué acceso tiene un cliente. TLDR: se hace a propósito por seguridad
error el
2
Tengo esto en mi archivo de configuración NGINX ... 'Access-Control-Expose-Headers' 'Authorization, X-Suggested-Filename, content-disposition' always; Todavía solo veo content-type: "application/pdf" realmente la necesidad de tirarcontent-disposition
Old Man Walter
17

Esto realmente me ayudó, gracias Nick Uraltsev por tu respuesta.

Para aquellos de ustedes que usan nodejs con cors :

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

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

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

En el caso de que envíe la respuesta en la forma de res.header('Authorization', `Bearer ${token}`).send();

Cass
fuente
1
Para aquellos que se preguntan, también podrían pasar una matriz aquí: expuestosHeaders: ['Autorización', 'X-Total-Count']
Thiago Santana
11

Estaba enfrentando el mismo problema. Hice esto en mi "WebSecurity.java", se trata del método setExposedHeaders en la configuración de cors.

@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;
}

Espero que funcione.

Daniel Azamar
fuente
7

Enfrenté el mismo problema en asp.net core Espero que esto ayude

public static class CorsConfig
{
    public static void AddCorsConfig(this IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                .WithExposedHeaders("X-Pagination")
                );
        });
    }
}
Chitova263
fuente
1
Bienvenido a SO! Su respuesta puede ser correcta, pero en StackOverflow, se desaconseja publicar solo el código. Intente proporcionar una explicación de cómo su respuesta resuelve la pregunta original. lea este sobre cómo escribir mejor respuesta
nircraft
Gracias, había ayudado;)
Florian
2

Según los documentos oficiales :

Esto puede ayudar si desea los encabezados HTTP con los que respondió el servidor . Todos los nombres de encabezado están en minúsculas y se puede acceder mediante la notación de corchetes. Ejemplo: response.headers['content-type']dará algo como: encabezados: {},

Yogesh Bhatt
fuente
1

Para el SpringBoot2 solo agregue

httpResponse.setHeader("Access-Control-Expose-Headers", "custom-header1, custom-header2");

a su código de implementación de filtro CORS para incluirlo en la lista blanca custom-header1y custom-header2etc.

JackTheKnife
fuente
0

para ayuda de django

CORS_EXPOSE_HEADERS = [
        'your header'
    ]
VladimirDev
fuente
0

Para Spring Boot 2, si no desea utilizar la configuración global de CORS, puede hacerlo por método o nivel de clase / controlador utilizando una @CrossOriginnotación con exposedHeadersatributo.

Por ejemplo, para agregar encabezado authorizationpara YourControllermétodos:

@CrossOrigin(exposedHeaders = "authorization")
@RestController
public class YourController {
    ...
}
M. Dudek
fuente