Axios obtém acesso aos campos de cabeçalho de resposta

160

Estou criando um aplicativo de front-end com React e Redux e estou usando axios para executar minhas solicitações. Gostaria de ter acesso a todos os campos no cabeçalho da resposta. No meu navegador, posso inspecionar o cabeçalho e ver que todos os campos necessários estão presentes (como token, uid, etc ...), mas quando ligo

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

Eu recebo apenas

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

Aqui, a guia Rede do meu navegador, como você pode ver, todos os outros campos estão presentes.

insira a descrição da imagem aqui

Bests.

TWONEKSONE
fonte
Se você imprimir axios.defaults.headers, isso fornecerá um dos que você está perdendo? Alguns cabeçalhos estão configurados nesse nível, não no de cada solicitação (consulte github.com/mzabriskie/axios#global-axios-defaults )
Ben Hare
2
Não é axios.defaults.headerspara configurar os parâmetros de cabeçalho REQUEST? Eu preciso acessar o RESPONSE. @BenHare
TWONEKSONE
BTW, o que você chamou de solicitação, não é uma solicitação. É uma promessa para sua resposta. Sua solicitação foi o que você passou para o método post () como argumentos.
Daniel

Respostas:

309

No caso de solicitações CORS, os navegadores podem acessar apenas os seguintes cabeçalhos de resposta por padrão:

  • Controle de cache
  • Idioma do Conteúdo
  • Tipo de conteúdo
  • Expira
  • Última modificação
  • Pragma

Se você deseja que seu aplicativo cliente possa acessar outros cabeçalhos, defina o cabeçalho Access-Control-Expose-Headers no servidor:

Access-Control-Expose-Headers: Access-Token, Uid
Nick Uraltsev
fonte
Meu mau eu esqueci de expor esses campos.
TWONEKSONE
27
Se você estiver usando Rails com Rack-Cors, precisará definir expose: ['Access-Token', 'Uid']a origem como:resource '*', :headers => :any, :methods => [:get, :post, :put, :patch, :delete, :options, :head], expose: ['Access-Token', 'Uid']
CWitty
3
Eu não entendo. Se eles não estão expostos, por que os cabeçalhos adicionais são visíveis no navegador, mas não na resposta dos axios?
adanilev
4
@adanilev, os navegadores permitem que você os veja para fins de depuração, mas impedem que você os acesse por APIs por motivos de segurança. Impede que os clientes obtenham credenciais protegidas dos servidores, permitindo que o servidor determine qual acesso um cliente tem. TLDR: feito de propósito para segurança
erfling
2
Eu tenho isso no meu arquivo confg NGINX ... 'Access-Control-Expose-Headers' 'Authorization, X-Suggested-Filename, content-disposition' always; Ainda só vejo content-type: "application/pdf" realmente precisa puxarcontent-disposition
Old Man Walter
17

Isso realmente me ajudou, obrigado Nick Uraltsev pela sua resposta.

Para aqueles que usam nodejs com cors :

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

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

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

No caso de você estar enviando a resposta no caminho de res.header('Authorization', `Bearer ${token}`).send();

cass
fonte
1
Para quem está se perguntando, você pode passar uma matriz aqui também: exposHeaders: ['Authorization', 'X-Total-Count']
Thiago Santana
11

Eu estava enfrentando o mesmo problema. Você fez isso no meu "WebSecurity.java", trata-se do método setExposedHeaders na configuração 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;
}

Eu espero que dê certo.

Daniel Azamar
fonte
7

Enfrentou o mesmo problema no núcleo do asp.net Espero que isso ajude

public static class CorsConfig
{
    public static void AddCorsConfig(this IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                .WithExposedHeaders("X-Pagination")
                );
        });
    }
}
Chitova263
fonte
1
Bem-vindo ao SO! Sua resposta pode estar correta, mas no StackOverflow, não é recomendável postar apenas a resposta do código. Tente fornecer uma explicação de como sua resposta resolve a pergunta original. leia este sobre como escrever melhor Resposta
nircraft
Obrigado, tinha ajudado;)
Florian
2

De acordo com documentos oficiais :

Isso pode ajudar se você desejar os cabeçalhos HTTP com os quais o servidor respondeu . Todos os nomes de cabeçalho são escritos em letras minúsculas e podem ser acessados ​​usando a notação entre colchetes. Exemplo: response.headers['content-type']fornecerá algo como: cabeçalhos: {},

Yogesh Bhatt
fonte
1

Para o SpringBoot2 basta adicionar

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

ao código de implementação do filtro CORS para ter uma lista de permissões custom-header1e custom-header2etc

JackTheKnife
fonte
0

para ajuda do django

CORS_EXPOSE_HEADERS = [
        'your header'
    ]
VladimirDev
fonte
0

Para o Spring Boot 2, se você não quiser usar a configuração global do CORS, poderá fazê-lo por método ou nível de classe / controlador usando uma @CrossOriginanotação com exposedHeadersatributo.

Por exemplo, para adicionar cabeçalho authorizationpara YourControllermétodos:

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